1/******************************************************************************
2 *
3 *  Copyright (C) 2012-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 *  Vendor-specific handler for DM events
22 *
23 ******************************************************************************/
24#include <string.h>
25#include "nfc_hal_int.h"
26#include "nfc_hal_post_reset.h"
27#include "upio.h"
28#include "userial.h"
29
30/*****************************************************************************
31** Constants and types
32*****************************************************************************/
33
34#define NFC_HAL_I93_RW_CFG_LEN (5)
35#define NFC_HAL_I93_RW_CFG_PARAM_LEN (3)
36#define NFC_HAL_I93_AFI (0)
37#define NFC_HAL_I93_ENABLE_SMART_POLL (1)
38
39static uint8_t nfc_hal_dm_i93_rw_cfg[NFC_HAL_I93_RW_CFG_LEN] = {
40    NCI_PARAM_ID_I93_DATARATE, NFC_HAL_I93_RW_CFG_PARAM_LEN,
41    NFC_HAL_I93_FLAG_DATA_RATE,   /* Bit0:Sub carrier, Bit1:Data rate,
42                                     Bit4:Enable/Disable AFI */
43    NFC_HAL_I93_AFI,              /* AFI if Bit 4 is set in the flag byte */
44    NFC_HAL_I93_ENABLE_SMART_POLL /* Bit0:Enable/Disable smart poll */
45};
46
47static uint8_t nfc_hal_dm_set_fw_fsm_cmd[NCI_MSG_HDR_SIZE + 1] = {
48    NCI_MTS_CMD | NCI_GID_PROP, NCI_MSG_SET_FWFSM, 0x01, 0x00,
49};
50#define NCI_SET_FWFSM_OFFSET_ENABLE 3
51
52/* length of parameters in XTAL_INDEX CMD */
53#define NCI_PROP_PARAM_SIZE_XTAL_INDEX 3
54#ifndef NCI_PROP_PARAM_MAX_SIZE_XTAL_INDEX
55#define NCI_PROP_PARAM_MAX_SIZE_XTAL_INDEX 20
56#endif
57
58const uint8_t nfc_hal_dm_get_build_info_cmd[NCI_MSG_HDR_SIZE] = {
59    NCI_MTS_CMD | NCI_GID_PROP, NCI_MSG_GET_BUILD_INFO, 0x00};
60#define NCI_BUILD_INFO_OFFSET_HWID 25 /* HW ID offset in build info RSP */
61
62const uint8_t nfc_hal_dm_get_patch_version_cmd[NCI_MSG_HDR_SIZE] = {
63    NCI_MTS_CMD | NCI_GID_PROP, NCI_MSG_GET_PATCH_VERSION, 0x00};
64/* Length of patch version string in PATCH_INFO */
65#define NCI_PATCH_INFO_VERSION_LEN 16
66
67/*****************************************************************************
68** Extern function prototypes
69*****************************************************************************/
70extern uint8_t* p_nfc_hal_dm_lptd_cfg;
71extern uint8_t* p_nfc_hal_dm_pll_325_cfg;
72extern uint8_t* p_nfc_hal_dm_start_up_cfg;
73extern uint8_t* p_nfc_hal_dm_start_up_vsc_cfg;
74extern tNFC_HAL_CFG* p_nfc_hal_cfg;
75extern tNFC_HAL_DM_PRE_SET_MEM* p_nfc_hal_dm_pre_set_mem;
76
77/*****************************************************************************
78** Local function prototypes
79*****************************************************************************/
80
81/*******************************************************************************
82**
83** Function         nfc_hal_dm_set_config
84**
85** Description      Send NCI config items to NFCC
86**
87** Returns          tHAL_NFC_STATUS
88**
89*******************************************************************************/
90tHAL_NFC_STATUS nfc_hal_dm_set_config(uint8_t tlv_size, uint8_t* p_param_tlvs,
91                                      tNFC_HAL_NCI_CBACK* p_cback) {
92  uint8_t *p_buff, *p;
93  uint8_t num_param = 0, param_len, rem_len, *p_tlv;
94  uint16_t cmd_len = NCI_MSG_HDR_SIZE + tlv_size + 1;
95  tHAL_NFC_STATUS status = HAL_NFC_STATUS_FAILED;
96
97  if ((tlv_size == 0) || (p_param_tlvs == NULL)) {
98    return status;
99  }
100
101  p_buff = (uint8_t*)GKI_getbuf((uint16_t)(NCI_MSG_HDR_SIZE + tlv_size));
102  if (p_buff != NULL) {
103    p = p_buff;
104
105    NCI_MSG_BLD_HDR0(p, NCI_MT_CMD, NCI_GID_CORE);
106    NCI_MSG_BLD_HDR1(p, NCI_MSG_CORE_SET_CONFIG);
107    UINT8_TO_STREAM(p, (uint8_t)(tlv_size + 1));
108
109    rem_len = tlv_size;
110    p_tlv = p_param_tlvs;
111    while (rem_len > 1) {
112      num_param++; /* number of params */
113
114      p_tlv++;              /* param type   */
115      param_len = *p_tlv++; /* param length */
116
117      rem_len -= 2; /* param type and length */
118      if (rem_len >= param_len) {
119        rem_len -= param_len;
120        p_tlv += param_len; /* next param_type */
121
122        if (rem_len == 0) {
123          status = HAL_NFC_STATUS_OK;
124          break;
125        }
126      } else {
127        /* error found */
128        break;
129      }
130    }
131
132    if (status == HAL_NFC_STATUS_OK) {
133      UINT8_TO_STREAM(p, num_param);
134      ARRAY_TO_STREAM(p, p_param_tlvs, tlv_size);
135
136      nfc_hal_dm_send_nci_cmd(p_buff, cmd_len, p_cback);
137    } else {
138      HAL_TRACE_ERROR0("nfc_hal_dm_set_config ():Bad TLV");
139    }
140
141    GKI_freebuf(p_buff);
142  }
143
144  return status;
145}
146
147/*******************************************************************************
148**
149** Function         nfc_hal_dm_set_fw_fsm
150**
151** Description      Enable or disable FW FSM
152**
153** Returns          void
154**
155*******************************************************************************/
156void nfc_hal_dm_set_fw_fsm(bool enable, tNFC_HAL_NCI_CBACK* p_cback) {
157  if (enable)
158    nfc_hal_dm_set_fw_fsm_cmd[NCI_SET_FWFSM_OFFSET_ENABLE] =
159        0x01; /* Enable, default is disabled */
160  else
161    nfc_hal_dm_set_fw_fsm_cmd[NCI_SET_FWFSM_OFFSET_ENABLE] = 0x00; /* Disable */
162
163  nfc_hal_dm_send_nci_cmd(nfc_hal_dm_set_fw_fsm_cmd, NCI_MSG_HDR_SIZE + 1,
164                          p_cback);
165}
166
167/*******************************************************************************
168**
169** Function         nfc_hal_dm_config_nfcc_cback
170**
171** Description      Callback for NCI vendor specific command complete
172**
173** Returns          void
174**
175*******************************************************************************/
176void nfc_hal_dm_config_nfcc_cback(tNFC_HAL_NCI_EVT event, uint16_t data_len,
177                                  uint8_t* p_data) {
178  if (nfc_hal_cb.dev_cb.next_dm_config == NFC_HAL_DM_CONFIG_NONE) {
179    nfc_hal_hci_enable();
180  } else {
181    nfc_hal_dm_config_nfcc();
182  }
183}
184
185/*******************************************************************************
186**
187** Function         nfc_hal_dm_send_startup_vsc
188**
189** Description      Send VS command before NFA start-up
190**
191** Returns          None
192**
193*******************************************************************************/
194void nfc_hal_dm_send_startup_vsc(void) {
195  uint8_t *p, *p_end;
196  uint16_t len;
197
198  HAL_TRACE_DEBUG0("nfc_hal_dm_send_startup_vsc ()");
199
200  /* VSC must have NCI header at least */
201  if (nfc_hal_cb.dev_cb.next_startup_vsc + NCI_MSG_HDR_SIZE - 1 <=
202      *p_nfc_hal_dm_start_up_vsc_cfg) {
203    p = p_nfc_hal_dm_start_up_vsc_cfg + nfc_hal_cb.dev_cb.next_startup_vsc;
204    len = *(p + 2);
205    p_end = p + NCI_MSG_HDR_SIZE - 1 + len;
206
207    if (p_end <=
208        p_nfc_hal_dm_start_up_vsc_cfg + *p_nfc_hal_dm_start_up_vsc_cfg) {
209      /* move to next VSC */
210      nfc_hal_cb.dev_cb.next_startup_vsc += NCI_MSG_HDR_SIZE + len;
211
212      /* if this is last VSC */
213      if (p_end ==
214          p_nfc_hal_dm_start_up_vsc_cfg + *p_nfc_hal_dm_start_up_vsc_cfg)
215        nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_NONE;
216
217      nfc_hal_dm_send_nci_cmd(p, (uint16_t)(NCI_MSG_HDR_SIZE + len),
218                              nfc_hal_dm_config_nfcc_cback);
219      return;
220    }
221  }
222
223  HAL_TRACE_ERROR0("nfc_hal_dm_send_startup_vsc (): Bad start-up VSC");
224
225  NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
226  nfc_hal_cb.p_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_FAILED);
227}
228
229/*******************************************************************************
230**
231** Function         nfc_hal_dm_config_nfcc
232**
233** Description      Send VS config before NFA start-up
234**
235** Returns          void
236**
237*******************************************************************************/
238void nfc_hal_dm_config_nfcc(void) {
239  HAL_TRACE_DEBUG1("nfc_hal_dm_config_nfcc (): next_dm_config = %d",
240                   nfc_hal_cb.dev_cb.next_dm_config);
241
242  if ((p_nfc_hal_dm_lptd_cfg[0]) &&
243      (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_LPTD)) {
244    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_PLL_325;
245
246    if (nfc_hal_dm_set_config(
247            p_nfc_hal_dm_lptd_cfg[0], &p_nfc_hal_dm_lptd_cfg[1],
248            nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) {
249      return;
250    } else {
251      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
252      nfc_hal_cb.p_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT,
253                               HAL_NFC_STATUS_FAILED);
254      return;
255    }
256  }
257
258  if ((p_nfc_hal_dm_pll_325_cfg) &&
259      (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_PLL_325)) {
260    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_START_UP;
261
262    if (nfc_hal_dm_set_config(
263            NFC_HAL_PLL_325_SETCONFIG_PARAM_LEN, p_nfc_hal_dm_pll_325_cfg,
264            nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) {
265      return;
266    } else {
267      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
268      nfc_hal_cb.p_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT,
269                               HAL_NFC_STATUS_FAILED);
270      return;
271    }
272  }
273
274  if ((p_nfc_hal_dm_start_up_cfg[0]) &&
275      (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_START_UP)) {
276    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_I93_DATA_RATE;
277    if (nfc_hal_dm_set_config(
278            p_nfc_hal_dm_start_up_cfg[0], &p_nfc_hal_dm_start_up_cfg[1],
279            nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) {
280      return;
281    } else {
282      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
283      nfc_hal_cb.p_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT,
284                               HAL_NFC_STATUS_FAILED);
285      return;
286    }
287  }
288
289#if (NFC_HAL_I93_FLAG_DATA_RATE == NFC_HAL_I93_FLAG_DATA_RATE_HIGH)
290  if (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_I93_DATA_RATE) {
291    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_FW_FSM;
292    if (nfc_hal_dm_set_config(NFC_HAL_I93_RW_CFG_LEN, nfc_hal_dm_i93_rw_cfg,
293                              nfc_hal_dm_config_nfcc_cback) ==
294        HAL_NFC_STATUS_OK) {
295      return;
296    } else {
297      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
298      nfc_hal_cb.p_stack_cback(HAL_NFC_POST_INIT_CPLT_EVT,
299                               HAL_NFC_STATUS_FAILED);
300      return;
301    }
302  }
303#endif
304
305  /* FW FSM is disabled as default in NFCC */
306  if (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_FW_FSM) {
307    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_START_UP_VSC;
308    nfc_hal_dm_set_fw_fsm(NFC_HAL_DM_MULTI_TECH_RESP,
309                          nfc_hal_dm_config_nfcc_cback);
310    return;
311  }
312
313  if (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_START_UP_VSC) {
314    if (p_nfc_hal_dm_start_up_vsc_cfg && *p_nfc_hal_dm_start_up_vsc_cfg) {
315      nfc_hal_dm_send_startup_vsc();
316      return;
317    }
318  }
319
320  /* nothing to config */
321  nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_NONE;
322  nfc_hal_dm_config_nfcc_cback(0, 0, NULL);
323}
324
325/*******************************************************************************
326**
327** Function:    nfc_hal_dm_get_xtal_index
328**
329** Description: Return Xtal index and frequency
330**
331** Returns:     tNFC_HAL_XTAL_INDEX
332**
333*******************************************************************************/
334tNFC_HAL_XTAL_INDEX nfc_hal_dm_get_xtal_index(uint32_t brcm_hw_id,
335                                              uint16_t* p_xtal_freq) {
336  uint8_t xx;
337
338  HAL_TRACE_DEBUG1("nfc_hal_dm_get_xtal_index() brcm_hw_id:0x%x", brcm_hw_id);
339
340  for (xx = 0; xx < nfc_post_reset_cb.dev_init_config.num_xtal_cfg; xx++) {
341    if ((brcm_hw_id & BRCM_NFC_GEN_MASK) ==
342        nfc_post_reset_cb.dev_init_config.xtal_cfg[xx].brcm_hw_id) {
343      *p_xtal_freq = nfc_post_reset_cb.dev_init_config.xtal_cfg[xx].xtal_freq;
344      return (nfc_post_reset_cb.dev_init_config.xtal_cfg[xx].xtal_index);
345    }
346  }
347
348  /* if not found */
349  *p_xtal_freq = 0;
350  return (NFC_HAL_XTAL_INDEX_MAX);
351}
352
353/*******************************************************************************
354**
355** Function         nfc_hal_dm_set_xtal_freq_index
356**
357** Description      Set crystal frequency index
358**
359** Returns          void
360**
361*******************************************************************************/
362void nfc_hal_dm_set_xtal_freq_index(void) {
363  uint8_t nci_brcm_xtal_index_cmd[NCI_MSG_HDR_SIZE +
364                                  NCI_PROP_PARAM_MAX_SIZE_XTAL_INDEX];
365  uint8_t* p;
366  tNFC_HAL_XTAL_INDEX xtal_index;
367  uint16_t xtal_freq;
368  uint8_t cmd_len = NCI_PROP_PARAM_SIZE_XTAL_INDEX;
369  extern uint8_t* p_nfc_hal_dm_xtal_params_cfg;
370
371  HAL_TRACE_DEBUG1("nfc_hal_dm_set_xtal_freq_index (): brcm_hw_id = 0x%x",
372                   nfc_hal_cb.dev_cb.brcm_hw_id);
373
374  xtal_index =
375      nfc_hal_dm_get_xtal_index(nfc_hal_cb.dev_cb.brcm_hw_id, &xtal_freq);
376  if ((xtal_index == NFC_HAL_XTAL_INDEX_SPECIAL) &&
377      (p_nfc_hal_dm_xtal_params_cfg)) {
378    cmd_len +=
379        p_nfc_hal_dm_xtal_params_cfg[0]; /* [0] is the length of extra params */
380  }
381
382  p = nci_brcm_xtal_index_cmd;
383  UINT8_TO_STREAM(p, (NCI_MTS_CMD | NCI_GID_PROP));
384  UINT8_TO_STREAM(p, NCI_MSG_GET_XTAL_INDEX_FROM_DH);
385  UINT8_TO_STREAM(p, cmd_len);
386  UINT8_TO_STREAM(p, xtal_index);
387  UINT16_TO_STREAM(p, xtal_freq);
388  if (cmd_len > NCI_PROP_PARAM_SIZE_XTAL_INDEX) {
389    memcpy(p, &p_nfc_hal_dm_xtal_params_cfg[1],
390           p_nfc_hal_dm_xtal_params_cfg[0]);
391  }
392
393  NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_XTAL_SET);
394
395  nfc_hal_dm_send_nci_cmd(nci_brcm_xtal_index_cmd, NCI_MSG_HDR_SIZE + cmd_len,
396                          NULL);
397}
398
399/*******************************************************************************
400**
401** Function         nfc_hal_dm_set_power_level_zero
402**
403** Description      set power level to 0
404**
405** Returns          None
406**
407*******************************************************************************/
408void nfc_hal_dm_set_power_level_zero(void) {
409  uint8_t
410      nci_brcm_set_pwr_level_cmd[NCI_MSG_HDR_SIZE + NCI_PARAM_LEN_POWER_LEVEL];
411  uint8_t* p;
412  uint8_t cmd_len = NCI_PARAM_LEN_POWER_LEVEL;
413
414  p = nci_brcm_set_pwr_level_cmd;
415  UINT8_TO_STREAM(p, (NCI_MTS_CMD | NCI_GID_PROP));
416  UINT8_TO_STREAM(p, NCI_MSG_POWER_LEVEL);
417  UINT8_TO_STREAM(p, NCI_PARAM_LEN_POWER_LEVEL);
418  memset(p, 0, NCI_PARAM_LEN_POWER_LEVEL);
419
420  nfc_hal_dm_send_nci_cmd(nci_brcm_set_pwr_level_cmd,
421                          NCI_MSG_HDR_SIZE + cmd_len,
422                          nfc_hal_main_exit_op_done);
423}
424
425/*******************************************************************************
426**
427** Function         nfc_hal_dm_send_get_build_info_cmd
428**
429** Description      Send NCI_MSG_GET_BUILD_INFO CMD
430**
431** Returns          void
432**
433*******************************************************************************/
434void nfc_hal_dm_send_get_build_info_cmd(void) {
435  NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_BUILD_INFO);
436
437  /* get build information to find out HW */
438  nfc_hal_dm_send_nci_cmd(nfc_hal_dm_get_build_info_cmd, NCI_MSG_HDR_SIZE,
439                          NULL);
440}
441/*******************************************************************************
442**
443** Function:    nfc_hal_dm_adjust_hw_id
444**
445** Description: The hw_id of certain chips are shifted by 8 bits.
446**              Adjust the hw_id before processing.
447**
448** Returns:     Nothing
449**
450*******************************************************************************/
451static uint32_t nfc_hal_dm_adjust_hw_id(uint32_t hw_id) {
452  if ((hw_id & 0xF0000000) == 0)
453    hw_id <<= 4; /* shift hw_id by 4 bits to align w the format of most chips */
454  return hw_id;
455}
456
457/*******************************************************************************
458**
459** Function         nfc_hal_dm_check_xtal
460**
461** Description      check if need to send xtal command.
462**                  If not, proceed to next step get_patch_version.
463**
464** Returns          void
465**
466*******************************************************************************/
467static void nfc_hal_dm_check_xtal(void) {
468  uint16_t xtal_freq;
469  tNFC_HAL_XTAL_INDEX xtal_index;
470
471  /* if NFCC needs to set Xtal frequency before getting patch version */
472  xtal_index =
473      nfc_hal_dm_get_xtal_index(nfc_hal_cb.dev_cb.brcm_hw_id, &xtal_freq);
474  if ((xtal_index < NFC_HAL_XTAL_INDEX_MAX) ||
475      (xtal_index == NFC_HAL_XTAL_INDEX_SPECIAL)) {
476    {
477      /* set Xtal index before getting patch version */
478      nfc_hal_dm_set_xtal_freq_index();
479      return;
480    }
481  }
482
483  NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_PATCH_INFO);
484
485  nfc_hal_dm_send_nci_cmd(nfc_hal_dm_get_patch_version_cmd, NCI_MSG_HDR_SIZE,
486                          NULL);
487}
488
489/*******************************************************************************
490**
491** Function         nfc_hal_dm_pre_set_mem_cback
492**
493** Description      This is pre-set mem complete callback.
494**
495** Returns          void
496**
497*******************************************************************************/
498static void nfc_hal_dm_pre_set_mem_cback(tNFC_HAL_BTVSC_CPLT* pData) {
499  uint8_t status = pData->p_param_buf[0];
500
501  HAL_TRACE_DEBUG1("nfc_hal_dm_pre_set_mem_cback: %d", status);
502  /* if it is completed */
503  if (status == HCI_SUCCESS) {
504    if (!nfc_hal_dm_check_pre_set_mem()) {
505      return;
506    }
507  }
508  nfc_hal_dm_check_xtal();
509}
510
511/*******************************************************************************
512**
513** Function         nfc_hal_dm_check_pre_set_mem
514**
515** Description      Check if need to send the command.
516**
517** Returns          TRUE if done.
518**
519*******************************************************************************/
520bool nfc_hal_dm_check_pre_set_mem(void) {
521  uint8_t cmd[NFC_HAL_BT_HCI_CMD_HDR_SIZE + HCI_BRCM_PRE_SET_MEM_LENGTH];
522  uint8_t* p;
523  uint32_t addr = 0;
524
525  if (p_nfc_hal_dm_pre_set_mem)
526    addr = p_nfc_hal_dm_pre_set_mem[nfc_hal_cb.pre_set_mem_idx].addr;
527  HAL_TRACE_DEBUG2("nfc_hal_dm_check_pre_set_mem: %d/0x%x",
528                   nfc_hal_cb.pre_set_mem_idx, addr);
529  if (addr == 0) {
530    return true;
531  }
532  p = cmd;
533
534  /* Add the command */
535  UINT16_TO_STREAM(p, HCI_BRCM_PRE_SET_MEM);
536  UINT8_TO_STREAM(p, HCI_BRCM_PRE_SET_MEM_LENGTH);
537
538  UINT8_TO_STREAM(p, HCI_BRCM_PRE_SET_MEM_TYPE);
539  UINT32_TO_STREAM(p, addr);
540  UINT8_TO_STREAM(p, 0);
541  UINT32_TO_STREAM(p,
542                   p_nfc_hal_dm_pre_set_mem[nfc_hal_cb.pre_set_mem_idx].data);
543  nfc_hal_cb.pre_set_mem_idx++;
544
545  nfc_hal_dm_send_bt_cmd(
546      cmd, NFC_HAL_BT_HCI_CMD_HDR_SIZE + HCI_BRCM_PRE_SET_MEM_LENGTH,
547      nfc_hal_dm_pre_set_mem_cback);
548  return false;
549}
550
551/*******************************************************************************
552**
553** Function         nfc_hal_dm_got_vs_rsp
554**
555** Description      Received VS RSP. Clean up control block to allow next NCI
556*cmd
557**
558** Returns          void
559**
560*******************************************************************************/
561tNFC_HAL_NCI_CBACK* nfc_hal_dm_got_vs_rsp(void) {
562  tNFC_HAL_NCI_CBACK* p_cback = NULL;
563  nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
564  p_cback = (tNFC_HAL_NCI_CBACK*)nfc_hal_cb.ncit_cb.p_vsc_cback;
565  nfc_hal_cb.ncit_cb.p_vsc_cback = NULL;
566  nfc_hal_main_stop_quick_timer(&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
567  return p_cback;
568}
569
570/*******************************************************************************
571**
572** Function         nfc_hal_dm_proc_msg_during_init
573**
574** Description      Process NCI message while initializing NFCC
575**
576** Returns          void
577**
578*******************************************************************************/
579void nfc_hal_dm_proc_msg_during_init(NFC_HDR* p_msg) {
580  uint8_t* p;
581  uint8_t reset_reason, reset_type;
582  uint8_t mt, pbf, gid, op_code;
583  uint8_t *p_old, old_gid, old_oid, old_mt;
584  uint8_t u8;
585  tNFC_HAL_NCI_CBACK* p_cback = NULL;
586  uint8_t chipverlen;
587  uint8_t chipverstr[NCI_SPD_HEADER_CHIPVER_LEN];
588  uint32_t hw_id = 0;
589
590  HAL_TRACE_DEBUG1("nfc_hal_dm_proc_msg_during_init(): init state:%d",
591                   nfc_hal_cb.dev_cb.initializing_state);
592
593  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
594
595  NCI_MSG_PRS_HDR0(p, mt, pbf, gid);
596  NCI_MSG_PRS_HDR1(p, op_code);
597
598  /* check if waiting for this response */
599  if ((nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_CMD) ||
600      (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_VSC)) {
601    if (mt == NCI_MT_RSP) {
602      p_old = nfc_hal_cb.ncit_cb.last_hdr;
603      NCI_MSG_PRS_HDR0(p_old, old_mt, pbf, old_gid);
604      old_oid = ((*p_old) & NCI_OID_MASK);
605      /* make sure this is the RSP we are waiting for before updating the
606       * command window */
607      if ((old_gid == gid) && (old_oid == op_code)) {
608        nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
609        p_cback = (tNFC_HAL_NCI_CBACK*)nfc_hal_cb.ncit_cb.p_vsc_cback;
610        nfc_hal_cb.ncit_cb.p_vsc_cback = NULL;
611        nfc_hal_main_stop_quick_timer(&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
612      }
613    }
614  }
615
616  if (gid == NCI_GID_CORE) {
617    if (op_code == NCI_MSG_CORE_RESET) {
618      if (mt == NCI_MT_NTF) {
619        if ((nfc_hal_cb.dev_cb.initializing_state ==
620             NFC_HAL_INIT_STATE_W4_NFCC_ENABLE) ||
621            (nfc_hal_cb.dev_cb.initializing_state ==
622             NFC_HAL_INIT_STATE_POST_XTAL_SET)) {
623          /*
624          ** Core reset ntf in the following cases;
625          ** 1) after power up (raising REG_PU)
626          ** 2) after setting xtal index
627          ** Start pre-initializing NFCC
628          */
629          nfc_hal_main_stop_quick_timer(&nfc_hal_cb.timer);
630          nfc_hal_dm_pre_init_nfcc();
631        } else {
632          /* Core reset ntf after post-patch download, Call reset notification
633           * callback */
634          p++; /* Skip over param len */
635          STREAM_TO_UINT8(reset_reason, p);
636          STREAM_TO_UINT8(reset_type, p);
637          nfc_hal_prm_spd_reset_ntf(reset_reason, reset_type);
638        }
639      }
640    } else if (p_cback) {
641      (*p_cback)((tNFC_HAL_NCI_EVT)(op_code), p_msg->len,
642                 (uint8_t*)(p_msg + 1) + p_msg->offset);
643    }
644  } else if (gid == NCI_GID_PROP) /* this is for download patch */
645  {
646    if (mt == NCI_MT_NTF)
647      op_code |= NCI_NTF_BIT;
648    else
649      op_code |= NCI_RSP_BIT;
650
651    if (nfc_hal_cb.dev_cb.initializing_state ==
652        NFC_HAL_INIT_STATE_W4_XTAL_SET) {
653      if (op_code == (NCI_RSP_BIT | NCI_MSG_GET_XTAL_INDEX_FROM_DH)) {
654        /* start timer in case that NFCC doesn't send RESET NTF after loading
655         * patch from NVM */
656        NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_POST_XTAL_SET);
657
658        nfc_hal_main_start_quick_timer(
659            &nfc_hal_cb.timer, NFC_HAL_TTYPE_NFCC_ENABLE,
660            ((p_nfc_hal_cfg->nfc_hal_post_xtal_timeout) *
661             QUICK_TIMER_TICKS_PER_SEC) /
662                1000);
663      }
664    } else if ((op_code == NFC_VS_GET_BUILD_INFO_EVT) &&
665               (nfc_hal_cb.dev_cb.initializing_state ==
666                NFC_HAL_INIT_STATE_W4_BUILD_INFO)) {
667      p += NCI_BUILD_INFO_OFFSET_HWID;
668
669      STREAM_TO_UINT32(hw_id, p);
670      nfc_hal_cb.dev_cb.brcm_hw_id = nfc_hal_dm_adjust_hw_id(hw_id);
671      HAL_TRACE_DEBUG2("brcm_hw_id: 0x%x -> 0x%x", hw_id,
672                       nfc_hal_cb.dev_cb.brcm_hw_id);
673
674      STREAM_TO_UINT8(chipverlen, p);
675      memset(chipverstr, 0, NCI_SPD_HEADER_CHIPVER_LEN);
676
677      STREAM_TO_ARRAY(chipverstr, p, chipverlen);
678
679      /* If chip is not 20791 and 43341, set flag to send the "Disable" VSC */
680      if (((nfc_hal_cb.dev_cb.brcm_hw_id & BRCM_NFC_GEN_MASK) !=
681           BRCM_NFC_20791_GEN) &&
682          ((nfc_hal_cb.dev_cb.brcm_hw_id & BRCM_NFC_GEN_MASK) !=
683           BRCM_NFC_43341_GEN)) {
684        nfc_hal_cb.hal_flags |= NFC_HAL_FLAGS_NEED_DISABLE_VSC;
685      }
686
687      nfc_hal_hci_handle_build_info(chipverlen, chipverstr);
688      nfc_hal_cb.pre_set_mem_idx = 0;
689      if (!nfc_hal_dm_check_pre_set_mem()) {
690        /* pre-set mem started */
691        return;
692      }
693      nfc_hal_dm_check_xtal();
694    } else if ((op_code == NFC_VS_GET_PATCH_VERSION_EVT) &&
695               (nfc_hal_cb.dev_cb.initializing_state ==
696                NFC_HAL_INIT_STATE_W4_PATCH_INFO)) {
697      /* Store NVM info to control block */
698
699      /* Skip over rsp len */
700      p++;
701
702      /* Get project id */
703      STREAM_TO_UINT16(nfc_hal_cb.nvm_cb.project_id, p);
704
705      /* RFU */
706      p++;
707
708      /* Get chip version string */
709      STREAM_TO_UINT8(u8, p);
710      if (u8 > NFC_HAL_PRM_MAX_CHIP_VER_LEN) u8 = NFC_HAL_PRM_MAX_CHIP_VER_LEN;
711      memcpy(nfc_hal_cb.nvm_cb.chip_ver, p, u8);
712      p += NCI_PATCH_INFO_VERSION_LEN;
713
714      /* Get major/minor version */
715      STREAM_TO_UINT16(nfc_hal_cb.nvm_cb.ver_major, p);
716      STREAM_TO_UINT16(nfc_hal_cb.nvm_cb.ver_minor, p);
717
718      /* Skip over max_size and patch_max_size */
719      p += 4;
720
721      /* Get current lpm patch size */
722      STREAM_TO_UINT16(nfc_hal_cb.nvm_cb.lpm_size, p);
723      STREAM_TO_UINT16(nfc_hal_cb.nvm_cb.fpm_size, p);
724
725      /* clear all flags which may be set during previous initialization */
726      nfc_hal_cb.nvm_cb.flags = 0;
727
728      /* Set patch present flag */
729      if ((nfc_hal_cb.nvm_cb.fpm_size) || (nfc_hal_cb.nvm_cb.lpm_size))
730        nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_PATCH_PRESENT;
731
732      /* LPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is
733       * present in nvm) */
734      STREAM_TO_UINT8(u8, p);
735      if (u8) {
736        /* LPM patch in NVM fails CRC check */
737        nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_LPM_BAD;
738      }
739
740      /* FPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is
741       * present in nvm) */
742      STREAM_TO_UINT8(u8, p);
743      if (u8) {
744        /* FPM patch in NVM fails CRC check */
745        nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_FPM_BAD;
746      }
747
748      /* Check if downloading patch to RAM only (no NVM) */
749      STREAM_TO_UINT8(nfc_hal_cb.nvm_cb.nvm_type, p);
750      if (nfc_hal_cb.nvm_cb.nvm_type == NCI_SPD_NVM_TYPE_NONE) {
751        nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_NO_NVM;
752      }
753
754      /* let platform update baudrate or download patch */
755      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_APP_COMPLETE);
756      nfc_hal_post_reset_init(nfc_hal_cb.dev_cb.brcm_hw_id,
757                              nfc_hal_cb.nvm_cb.nvm_type);
758    } else if (p_cback) {
759      (*p_cback)((tNFC_HAL_NCI_EVT)(op_code), p_msg->len,
760                 (uint8_t*)(p_msg + 1) + p_msg->offset);
761    } else if (op_code == NFC_VS_SEC_PATCH_AUTH_EVT) {
762      HAL_TRACE_DEBUG0("signature!!");
763      nfc_hal_prm_nci_command_complete_cback(
764          (tNFC_HAL_NCI_EVT)(op_code), p_msg->len,
765          (uint8_t*)(p_msg + 1) + p_msg->offset);
766    }
767  }
768}
769
770/*******************************************************************************
771**
772** Function         nfc_hal_dm_proc_msg_during_exit
773**
774** Description      Process NCI message while shutting down NFCC
775**
776** Returns          void
777**
778*******************************************************************************/
779void nfc_hal_dm_proc_msg_during_exit(NFC_HDR* p_msg) {
780  uint8_t* p;
781  uint8_t mt, pbf, gid, op_code;
782  uint8_t *p_old, old_gid, old_oid, old_mt;
783  uint8_t u8;
784  tNFC_HAL_NCI_CBACK* p_cback = NULL;
785
786  HAL_TRACE_DEBUG1("nfc_hal_dm_proc_msg_during_exit(): state:%d",
787                   nfc_hal_cb.dev_cb.initializing_state);
788
789  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
790
791  NCI_MSG_PRS_HDR0(p, mt, pbf, gid);
792  NCI_MSG_PRS_HDR1(p, op_code);
793  u8 = *p;
794
795  /* check if waiting for this response */
796  if ((nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_CMD) ||
797      (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_VSC)) {
798    if (mt == NCI_MT_RSP) {
799      p_old = nfc_hal_cb.ncit_cb.last_hdr;
800      NCI_MSG_PRS_HDR0(p_old, old_mt, pbf, old_gid);
801      old_oid = ((*p_old) & NCI_OID_MASK);
802      /* make sure this is the RSP we are waiting for before updating the
803       * command window */
804      if ((old_gid == gid) && (old_oid == op_code)) {
805        p_cback = nfc_hal_dm_got_vs_rsp();
806        if (p_cback) {
807          if (gid == NCI_GID_PROP) {
808            if (mt == NCI_MT_NTF)
809              op_code |= NCI_NTF_BIT;
810            else
811              op_code |= NCI_RSP_BIT;
812
813            if (op_code == NFC_VS_POWER_LEVEL_RSP) {
814              (*p_cback)((tNFC_HAL_NCI_EVT)(op_code), p_msg->len,
815                         (uint8_t*)(p_msg + 1) + p_msg->offset);
816            }
817          }
818        }
819      }
820    }
821  }
822}
823
824/*******************************************************************************
825**
826** Function         nfc_hal_dm_send_nci_cmd
827**
828** Description      Send NCI command to NFCC while initializing BRCM NFCC
829**
830** Returns          void
831**
832*******************************************************************************/
833void nfc_hal_dm_send_nci_cmd(const uint8_t* p_data, uint16_t len,
834                             tNFC_HAL_NCI_CBACK* p_cback) {
835  NFC_HDR* p_buf;
836  uint8_t* ps;
837
838  HAL_TRACE_DEBUG1("nfc_hal_dm_send_nci_cmd (): nci_wait_rsp = 0x%x",
839                   nfc_hal_cb.ncit_cb.nci_wait_rsp);
840
841  if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) {
842    HAL_TRACE_ERROR0("nfc_hal_dm_send_nci_cmd(): no command window");
843    return;
844  }
845
846  p_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_HAL_NCI_POOL_ID);
847  if (p_buf != NULL) {
848    nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_VSC;
849
850    p_buf->offset = NFC_HAL_NCI_MSG_OFFSET_SIZE;
851    p_buf->event = NFC_HAL_EVT_TO_NFC_NCI;
852    p_buf->len = len;
853
854    memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, len);
855
856    /* Keep a copy of the command and send to NCI transport */
857
858    /* save the message header to double check the response */
859    ps = (uint8_t*)(p_buf + 1) + p_buf->offset;
860    memcpy(nfc_hal_cb.ncit_cb.last_hdr, ps, NFC_HAL_SAVED_HDR_SIZE);
861    memcpy(nfc_hal_cb.ncit_cb.last_cmd, ps + NCI_MSG_HDR_SIZE,
862           NFC_HAL_SAVED_CMD_SIZE);
863
864    /* save the callback for NCI VSCs */
865    nfc_hal_cb.ncit_cb.p_vsc_cback = (void*)p_cback;
866
867    nfc_hal_nci_send_cmd(p_buf);
868
869    /* start NFC command-timeout timer */
870    nfc_hal_main_start_quick_timer(
871        &nfc_hal_cb.ncit_cb.nci_wait_rsp_timer,
872        (uint16_t)(NFC_HAL_TTYPE_NCI_WAIT_RSP),
873        ((uint32_t)NFC_HAL_CMD_TOUT) * QUICK_TIMER_TICKS_PER_SEC / 1000);
874  }
875}
876
877/*******************************************************************************
878**
879** Function         nfc_hal_dm_send_pend_cmd
880**
881** Description      Send a command to NFCC
882**
883** Returns          void
884**
885*******************************************************************************/
886void nfc_hal_dm_send_pend_cmd(void) {
887  NFC_HDR* p_buf = nfc_hal_cb.ncit_cb.p_pend_cmd;
888  uint8_t* p;
889
890  if (p_buf == NULL) return;
891
892  /* check low power mode state */
893  if (!nfc_hal_dm_power_mode_execute(NFC_HAL_LP_TX_DATA_EVT)) {
894    return;
895  }
896
897  if (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_PROP) {
898#if (NFC_HAL_TRACE_PROTOCOL == TRUE)
899    DispHciCmd(p_buf);
900#endif
901
902    /* save the message header to double check the response */
903    p = (uint8_t*)(p_buf + 1) + p_buf->offset;
904    memcpy(nfc_hal_cb.ncit_cb.last_hdr, p, NFC_HAL_SAVED_HDR_SIZE);
905
906    /* add packet type for BT message */
907    p_buf->offset--;
908    p_buf->len++;
909
910    p = (uint8_t*)(p_buf + 1) + p_buf->offset;
911    *p = HCIT_TYPE_COMMAND;
912
913    USERIAL_Write(USERIAL_NFC_PORT, p, p_buf->len);
914
915    GKI_freebuf(p_buf);
916    nfc_hal_cb.ncit_cb.p_pend_cmd = NULL;
917
918    /* start NFC command-timeout timer */
919    nfc_hal_main_start_quick_timer(
920        &nfc_hal_cb.ncit_cb.nci_wait_rsp_timer,
921        (uint16_t)(NFC_HAL_TTYPE_NCI_WAIT_RSP),
922        ((uint32_t)NFC_HAL_CMD_TOUT) * QUICK_TIMER_TICKS_PER_SEC / 1000);
923  }
924}
925
926/*******************************************************************************
927**
928** Function         nfc_hal_dm_send_bt_cmd
929**
930** Description      Send BT message to NFCC while initializing BRCM NFCC
931**
932** Returns          void
933**
934*******************************************************************************/
935void nfc_hal_dm_send_bt_cmd(const uint8_t* p_data, uint16_t len,
936                            tNFC_HAL_BTVSC_CPLT_CBACK* p_cback) {
937  NFC_HDR* p_buf;
938  char buff[300];
939  char tmp[4];
940  buff[0] = 0;
941  int i;
942
943  HAL_TRACE_DEBUG1("nfc_hal_dm_send_bt_cmd (): nci_wait_rsp = 0x%x",
944                   nfc_hal_cb.ncit_cb.nci_wait_rsp);
945
946  for (i = 0; i < len; i++) {
947    sprintf(tmp, "%02x ", p_data[i]);
948    strcat(buff, tmp);
949  }
950  HAL_TRACE_DEBUG2("nfc_hal_dm_send_bt_cmd (): HCI Write (%d bytes): %s", len,
951                   buff);
952
953  if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) {
954    HAL_TRACE_ERROR0("nfc_hal_dm_send_bt_cmd(): no command window");
955    return;
956  }
957
958  p_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_HAL_NCI_POOL_ID);
959  if (p_buf != NULL) {
960    nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_PROP;
961
962    p_buf->offset = NFC_HAL_NCI_MSG_OFFSET_SIZE;
963    p_buf->len = len;
964
965    memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, len);
966
967    /* save the callback for NCI VSCs)  */
968    nfc_hal_cb.ncit_cb.p_vsc_cback = (void*)p_cback;
969
970    nfc_hal_cb.ncit_cb.p_pend_cmd = p_buf;
971    if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE) {
972      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_CONTROL_DONE);
973      nfc_hal_cb.p_stack_cback(HAL_NFC_REQUEST_CONTROL_EVT, HAL_NFC_STATUS_OK);
974      return;
975    }
976
977    nfc_hal_dm_send_pend_cmd();
978  }
979}
980
981/*******************************************************************************
982**
983** Function         nfc_hal_dm_set_nfc_wake
984**
985** Description      Set NFC_WAKE line
986**
987** Returns          void
988**
989*******************************************************************************/
990void nfc_hal_dm_set_nfc_wake(uint8_t cmd) {
991  HAL_TRACE_DEBUG1("nfc_hal_dm_set_nfc_wake () %s",
992                   (cmd == NFC_HAL_ASSERT_NFC_WAKE ? "ASSERT" : "DEASSERT"));
993
994  /*
995  **  nfc_wake_active_mode             cmd              result of voltage on
996  *NFC_WAKE
997  **
998  **  NFC_HAL_LP_ACTIVE_LOW (0)    NFC_HAL_ASSERT_NFC_WAKE (0)    pull down
999  *NFC_WAKE (GND)
1000  **  NFC_HAL_LP_ACTIVE_LOW (0)    NFC_HAL_DEASSERT_NFC_WAKE (1)  pull up
1001  *NFC_WAKE (VCC)
1002  **  NFC_HAL_LP_ACTIVE_HIGH (1)   NFC_HAL_ASSERT_NFC_WAKE (0)    pull up
1003  *NFC_WAKE (VCC)
1004  **  NFC_HAL_LP_ACTIVE_HIGH (1)   NFC_HAL_DEASSERT_NFC_WAKE (1)  pull down
1005  *NFC_WAKE (GND)
1006  */
1007
1008  if (cmd == nfc_hal_cb.dev_cb.nfc_wake_active_mode)
1009    UPIO_Set(UPIO_GENERAL, NFC_HAL_LP_NFC_WAKE_GPIO,
1010             UPIO_OFF); /* pull down NFC_WAKE */
1011  else
1012    UPIO_Set(UPIO_GENERAL, NFC_HAL_LP_NFC_WAKE_GPIO,
1013             UPIO_ON); /* pull up NFC_WAKE */
1014}
1015
1016/*******************************************************************************
1017**
1018** Function         nfc_hal_dm_power_mode_execute
1019**
1020** Description      If snooze mode is enabled in full power mode,
1021**                     Assert NFC_WAKE before sending data
1022**                     Deassert NFC_WAKE when idle timer expires
1023**
1024** Returns          TRUE if DH can send data to NFCC
1025**
1026*******************************************************************************/
1027bool nfc_hal_dm_power_mode_execute(tNFC_HAL_LP_EVT event) {
1028  bool send_to_nfcc = false;
1029
1030  HAL_TRACE_DEBUG1("nfc_hal_dm_power_mode_execute () event = %d", event);
1031
1032  if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) {
1033    if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) {
1034      /* if any transport activity */
1035      if ((event == NFC_HAL_LP_TX_DATA_EVT) ||
1036          (event == NFC_HAL_LP_RX_DATA_EVT)) {
1037        /* if idle timer is not running */
1038        if (nfc_hal_cb.dev_cb.lp_timer.in_use == false) {
1039          nfc_hal_dm_set_nfc_wake(NFC_HAL_ASSERT_NFC_WAKE);
1040        }
1041
1042        /* start or extend idle timer */
1043        nfc_hal_main_start_quick_timer(&nfc_hal_cb.dev_cb.lp_timer, 0x00,
1044                                       ((uint32_t)NFC_HAL_LP_IDLE_TIMEOUT) *
1045                                           QUICK_TIMER_TICKS_PER_SEC / 1000);
1046      } else if (event == NFC_HAL_LP_TIMEOUT_EVT) {
1047        /* let NFCC go to snooze mode */
1048        nfc_hal_dm_set_nfc_wake(NFC_HAL_DEASSERT_NFC_WAKE);
1049      }
1050    }
1051
1052    send_to_nfcc = true;
1053  }
1054
1055  return (send_to_nfcc);
1056}
1057
1058/*******************************************************************************
1059**
1060** Function         nci_brcm_lp_timeout_cback
1061**
1062** Description      callback function for low power timeout
1063**
1064** Returns          void
1065**
1066*******************************************************************************/
1067static void nci_brcm_lp_timeout_cback(void* p_tle) {
1068  HAL_TRACE_DEBUG0("nci_brcm_lp_timeout_cback ()");
1069
1070  nfc_hal_dm_power_mode_execute(NFC_HAL_LP_TIMEOUT_EVT);
1071}
1072
1073/*******************************************************************************
1074**
1075** Function         nfc_hal_dm_pre_init_nfcc
1076**
1077** Description      This function initializes Broadcom specific control blocks
1078*for
1079**                  NCI transport
1080**
1081** Returns          void
1082**
1083*******************************************************************************/
1084void nfc_hal_dm_pre_init_nfcc(void) {
1085  HAL_TRACE_DEBUG0("nfc_hal_dm_pre_init_nfcc ()");
1086
1087  /* if it was waiting for core reset notification after raising REG_PU */
1088  if (nfc_hal_cb.dev_cb.initializing_state ==
1089      NFC_HAL_INIT_STATE_W4_NFCC_ENABLE) {
1090    nfc_hal_dm_send_get_build_info_cmd();
1091  }
1092  /* if it was waiting for core reset notification after setting Xtal */
1093  else if (nfc_hal_cb.dev_cb.initializing_state ==
1094           NFC_HAL_INIT_STATE_POST_XTAL_SET) {
1095    {
1096      /* Core reset ntf after xtal setting indicating NFCC loaded patch from NVM
1097       */
1098      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_PATCH_INFO);
1099
1100      nfc_hal_dm_send_nci_cmd(nfc_hal_dm_get_patch_version_cmd,
1101                              NCI_MSG_HDR_SIZE, NULL);
1102    }
1103  }
1104}
1105
1106/*******************************************************************************
1107**
1108** Function         nfc_hal_dm_shutting_down_nfcc
1109**
1110** Description      This function initializes Broadcom specific control blocks
1111*for
1112**                  NCI transport
1113**
1114** Returns          void
1115**
1116*******************************************************************************/
1117void nfc_hal_dm_shutting_down_nfcc(void) {
1118  HAL_TRACE_DEBUG0("nfc_hal_dm_shutting_down_nfcc ()");
1119
1120  nfc_hal_cb.dev_cb.initializing_state = NFC_HAL_INIT_STATE_CLOSING;
1121
1122  /* reset low power mode variables */
1123  if ((nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) &&
1124      (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE)) {
1125    nfc_hal_dm_set_nfc_wake(NFC_HAL_ASSERT_NFC_WAKE);
1126  }
1127
1128  nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
1129
1130  nfc_hal_cb.dev_cb.power_mode = NFC_HAL_POWER_MODE_FULL;
1131  nfc_hal_cb.dev_cb.snooze_mode = NFC_HAL_LP_SNOOZE_MODE_NONE;
1132
1133  /* Stop all timers */
1134  nfc_hal_main_stop_quick_timer(&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
1135  nfc_hal_main_stop_quick_timer(&nfc_hal_cb.dev_cb.lp_timer);
1136  nfc_hal_main_stop_quick_timer(&nfc_hal_cb.prm.timer);
1137#if (NFC_HAL_HCI_INCLUDED == TRUE)
1138  nfc_hal_cb.hci_cb.hcp_conn_id = 0;
1139  nfc_hal_main_stop_quick_timer(&nfc_hal_cb.hci_cb.hci_timer);
1140#endif
1141  nfc_hal_main_stop_quick_timer(&nfc_hal_cb.timer);
1142}
1143
1144/*******************************************************************************
1145**
1146** Function         nfc_hal_dm_init
1147**
1148** Description      This function initializes Broadcom specific control blocks
1149*for
1150**                  NCI transport
1151**
1152** Returns          void
1153**
1154*******************************************************************************/
1155void nfc_hal_dm_init(void) {
1156  HAL_TRACE_DEBUG0("nfc_hal_dm_init ()");
1157
1158  nfc_hal_cb.dev_cb.lp_timer.p_cback = nci_brcm_lp_timeout_cback;
1159
1160  nfc_hal_cb.ncit_cb.nci_wait_rsp_timer.p_cback = nfc_hal_nci_cmd_timeout_cback;
1161
1162#if (NFC_HAL_HCI_INCLUDED == TRUE)
1163  nfc_hal_cb.hci_cb.hci_timer.p_cback = nfc_hal_hci_timeout_cback;
1164#endif
1165
1166  nfc_hal_cb.pre_discover_done = false;
1167
1168  nfc_post_reset_cb.spd_nvm_detection_cur_count = 0;
1169  nfc_post_reset_cb.spd_skip_on_power_cycle = false;
1170}
1171
1172/*******************************************************************************
1173**
1174** Function         HAL_NfcDevInitDone
1175**
1176** Description      Notify that pre-initialization of NFCC is complete
1177**
1178** Returns          void
1179**
1180*******************************************************************************/
1181void HAL_NfcPreInitDone(tHAL_NFC_STATUS status) {
1182  HAL_TRACE_DEBUG1("HAL_NfcPreInitDone () status=%d", status);
1183
1184  if (nfc_hal_cb.dev_cb.initializing_state ==
1185      NFC_HAL_INIT_STATE_W4_APP_COMPLETE) {
1186    NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
1187
1188    nfc_hal_main_pre_init_done(status);
1189  }
1190}
1191
1192/*******************************************************************************
1193**
1194** Function         HAL_NfcReInit
1195**
1196** Description      This function is called to restart initialization after
1197*REG_PU
1198**                  toggled because of failure to detect NVM type or download
1199*patchram.
1200**
1201** Note             This function should be called only during the HAL init
1202*process
1203**
1204** Returns          HAL_NFC_STATUS_OK if successfully initiated
1205**                  HAL_NFC_STATUS_FAILED otherwise
1206**
1207*******************************************************************************/
1208tHAL_NFC_STATUS HAL_NfcReInit(void) {
1209  tHAL_NFC_STATUS status = HAL_NFC_STATUS_FAILED;
1210
1211  HAL_TRACE_DEBUG1("HAL_NfcReInit () init st=0x%x",
1212                   nfc_hal_cb.dev_cb.initializing_state);
1213  if (nfc_hal_cb.dev_cb.initializing_state ==
1214      NFC_HAL_INIT_STATE_W4_APP_COMPLETE) {
1215    {
1216      /* Wait for NFCC to enable - Core reset notification */
1217      NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_NFCC_ENABLE);
1218
1219      /* NFCC Enable timeout */
1220      nfc_hal_main_start_quick_timer(
1221          &nfc_hal_cb.timer, NFC_HAL_TTYPE_NFCC_ENABLE,
1222          ((p_nfc_hal_cfg->nfc_hal_nfcc_enable_timeout) *
1223           QUICK_TIMER_TICKS_PER_SEC) /
1224              1000);
1225    }
1226
1227    status = HAL_NFC_STATUS_OK;
1228  }
1229  return status;
1230}
1231
1232/*******************************************************************************
1233**
1234** Function         nfc_hal_dm_set_snooze_mode_cback
1235**
1236** Description      This is snooze update complete callback.
1237**
1238** Returns          void
1239**
1240*******************************************************************************/
1241static void nfc_hal_dm_set_snooze_mode_cback(tNFC_HAL_BTVSC_CPLT* pData) {
1242  uint8_t status = pData->p_param_buf[0];
1243  tHAL_NFC_STATUS hal_status;
1244  tHAL_NFC_STATUS_CBACK* p_cback;
1245
1246  /* if it is completed */
1247  if (status == HCI_SUCCESS) {
1248    /* update snooze mode */
1249    nfc_hal_cb.dev_cb.snooze_mode = nfc_hal_cb.dev_cb.new_snooze_mode;
1250
1251    nfc_hal_dm_set_nfc_wake(NFC_HAL_ASSERT_NFC_WAKE);
1252
1253    if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) {
1254      /* start idle timer */
1255      nfc_hal_main_start_quick_timer(&nfc_hal_cb.dev_cb.lp_timer, 0x00,
1256                                     ((uint32_t)NFC_HAL_LP_IDLE_TIMEOUT) *
1257                                         QUICK_TIMER_TICKS_PER_SEC / 1000);
1258    } else {
1259      nfc_hal_main_stop_quick_timer(&nfc_hal_cb.dev_cb.lp_timer);
1260    }
1261    hal_status = HAL_NFC_STATUS_OK;
1262  } else {
1263    hal_status = HAL_NFC_STATUS_FAILED;
1264  }
1265
1266  if (nfc_hal_cb.dev_cb.p_prop_cback) {
1267    p_cback = nfc_hal_cb.dev_cb.p_prop_cback;
1268    nfc_hal_cb.dev_cb.p_prop_cback = NULL;
1269    (*p_cback)(hal_status);
1270  }
1271}
1272
1273/*******************************************************************************
1274**
1275** Function         HAL_NfcSetSnoozeMode
1276**
1277** Description      Set snooze mode
1278**                  snooze_mode
1279**                      NFC_HAL_LP_SNOOZE_MODE_NONE - Snooze mode disabled
1280**                      NFC_HAL_LP_SNOOZE_MODE_UART - Snooze mode for UART
1281**                      NFC_HAL_LP_SNOOZE_MODE_SPI_I2C - Snooze mode for SPI/I2C
1282**
1283**                  idle_threshold_dh/idle_threshold_nfcc
1284**                      Idle Threshold Host in 100ms unit
1285**
1286**                  nfc_wake_active_mode/dh_wake_active_mode
1287**                      NFC_HAL_LP_ACTIVE_LOW - high to low voltage is asserting
1288**                      NFC_HAL_LP_ACTIVE_HIGH - low to high voltage is
1289*asserting
1290**
1291**                  p_snooze_cback
1292**                      Notify status of operation
1293**
1294** Returns          tHAL_NFC_STATUS
1295**
1296*******************************************************************************/
1297tHAL_NFC_STATUS HAL_NfcSetSnoozeMode(uint8_t snooze_mode,
1298                                     uint8_t idle_threshold_dh,
1299                                     uint8_t idle_threshold_nfcc,
1300                                     uint8_t nfc_wake_active_mode,
1301                                     uint8_t dh_wake_active_mode,
1302                                     tHAL_NFC_STATUS_CBACK* p_snooze_cback) {
1303  uint8_t cmd[NFC_HAL_BT_HCI_CMD_HDR_SIZE + HCI_BRCM_WRITE_SLEEP_MODE_LENGTH];
1304  uint8_t* p;
1305
1306  HAL_TRACE_API1("HAL_NfcSetSnoozeMode (): snooze_mode = %d", snooze_mode);
1307
1308  nfc_hal_cb.dev_cb.new_snooze_mode = snooze_mode;
1309  nfc_hal_cb.dev_cb.nfc_wake_active_mode = nfc_wake_active_mode;
1310  nfc_hal_cb.dev_cb.p_prop_cback = p_snooze_cback;
1311
1312  p = cmd;
1313
1314  /* Add the HCI command */
1315  UINT16_TO_STREAM(p, HCI_BRCM_WRITE_SLEEP_MODE);
1316  UINT8_TO_STREAM(p, HCI_BRCM_WRITE_SLEEP_MODE_LENGTH);
1317
1318  memset(p, 0x00, HCI_BRCM_WRITE_SLEEP_MODE_LENGTH);
1319
1320  UINT8_TO_STREAM(p, snooze_mode); /* Sleep Mode               */
1321
1322  UINT8_TO_STREAM(p, idle_threshold_dh);    /* Idle Threshold Host      */
1323  UINT8_TO_STREAM(p, idle_threshold_nfcc);  /* Idle Threshold HC        */
1324  UINT8_TO_STREAM(p, nfc_wake_active_mode); /* BT Wake Active Mode      */
1325  UINT8_TO_STREAM(p, dh_wake_active_mode);  /* Host Wake Active Mode    */
1326
1327  nfc_hal_dm_send_bt_cmd(
1328      cmd, NFC_HAL_BT_HCI_CMD_HDR_SIZE + HCI_BRCM_WRITE_SLEEP_MODE_LENGTH,
1329      nfc_hal_dm_set_snooze_mode_cback);
1330  return (NCI_STATUS_OK);
1331}
1332