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 
39 static 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 
47 static 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 
58 const 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 
62 const 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 *****************************************************************************/
70 extern uint8_t* p_nfc_hal_dm_lptd_cfg;
71 extern uint8_t* p_nfc_hal_dm_pll_325_cfg;
72 extern uint8_t* p_nfc_hal_dm_start_up_cfg;
73 extern uint8_t* p_nfc_hal_dm_start_up_vsc_cfg;
74 extern tNFC_HAL_CFG* p_nfc_hal_cfg;
75 extern 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 *******************************************************************************/
nfc_hal_dm_set_config(uint8_t tlv_size,uint8_t * p_param_tlvs,tNFC_HAL_NCI_CBACK * p_cback)90 tHAL_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 *******************************************************************************/
nfc_hal_dm_set_fw_fsm(bool enable,tNFC_HAL_NCI_CBACK * p_cback)156 void 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 *******************************************************************************/
nfc_hal_dm_config_nfcc_cback(tNFC_HAL_NCI_EVT event,uint16_t data_len,uint8_t * p_data)176 void 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 *******************************************************************************/
nfc_hal_dm_send_startup_vsc(void)194 void 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 *******************************************************************************/
nfc_hal_dm_config_nfcc(void)238 void 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 *******************************************************************************/
nfc_hal_dm_get_xtal_index(uint32_t brcm_hw_id,uint16_t * p_xtal_freq)334 tNFC_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 *******************************************************************************/
nfc_hal_dm_set_xtal_freq_index(void)362 void 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 *******************************************************************************/
nfc_hal_dm_set_power_level_zero(void)408 void 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 *******************************************************************************/
nfc_hal_dm_send_get_build_info_cmd(void)434 void 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 *******************************************************************************/
nfc_hal_dm_adjust_hw_id(uint32_t hw_id)451 static 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 *******************************************************************************/
nfc_hal_dm_check_xtal(void)467 static 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 *******************************************************************************/
nfc_hal_dm_pre_set_mem_cback(tNFC_HAL_BTVSC_CPLT * pData)498 static 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 *******************************************************************************/
nfc_hal_dm_check_pre_set_mem(void)520 bool 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 *******************************************************************************/
nfc_hal_dm_got_vs_rsp(void)561 tNFC_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 *******************************************************************************/
nfc_hal_dm_proc_msg_during_init(NFC_HDR * p_msg)579 void 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 *******************************************************************************/
nfc_hal_dm_proc_msg_during_exit(NFC_HDR * p_msg)779 void 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 *******************************************************************************/
nfc_hal_dm_send_nci_cmd(const uint8_t * p_data,uint16_t len,tNFC_HAL_NCI_CBACK * p_cback)833 void 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 *******************************************************************************/
nfc_hal_dm_send_pend_cmd(void)886 void 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 *******************************************************************************/
nfc_hal_dm_send_bt_cmd(const uint8_t * p_data,uint16_t len,tNFC_HAL_BTVSC_CPLT_CBACK * p_cback)935 void 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 *******************************************************************************/
nfc_hal_dm_set_nfc_wake(uint8_t cmd)990 void 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 *******************************************************************************/
nfc_hal_dm_power_mode_execute(tNFC_HAL_LP_EVT event)1027 bool 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 *******************************************************************************/
nci_brcm_lp_timeout_cback(void * p_tle)1067 static 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 *******************************************************************************/
nfc_hal_dm_pre_init_nfcc(void)1084 void 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 *******************************************************************************/
nfc_hal_dm_shutting_down_nfcc(void)1117 void 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 *******************************************************************************/
nfc_hal_dm_init(void)1155 void 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 *******************************************************************************/
HAL_NfcPreInitDone(tHAL_NFC_STATUS status)1181 void 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 *******************************************************************************/
HAL_NfcReInit(void)1208 tHAL_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 *******************************************************************************/
nfc_hal_dm_set_snooze_mode_cback(tNFC_HAL_BTVSC_CPLT * pData)1241 static 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 *******************************************************************************/
HAL_NfcSetSnoozeMode(uint8_t snooze_mode,uint8_t idle_threshold_dh,uint8_t idle_threshold_nfcc,uint8_t nfc_wake_active_mode,uint8_t dh_wake_active_mode,tHAL_NFC_STATUS_CBACK * p_snooze_cback)1297 tHAL_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