/******************************************************************************* ** ** Function nfc_hal_main_userial_cback ** ** Description USERIAL callback for NCI transport ** ** Returns nothing ** *******************************************************************************/ static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data) { if (evt == USERIAL_RX_READY_EVT) { /* Notify transport task of serial port event */ GKI_send_event (NFC_HAL_TASK, NFC_HAL_TASK_EVT_DATA_RDY); } else if (evt == USERIAL_TX_DONE_EVT) { /* Serial driver has finshed sending data from USERIAL_Write */ /* Currently, no action is needed for this event */ } else if (evt == USERIAL_ERR_EVT) { HAL_TRACE_ERROR0 ("nfc_hal_main_userial_cback: USERIAL_ERR_EVT. Notifying NFC_TASK of transport error"); if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) { nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); nfc_hal_nci_cmd_timeout_cback ((void *)&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); } else { nfc_hal_main_send_error (HAL_NFC_STATUS_ERR_TRANSPORT); } } else if (evt == USERIAL_WAKEUP_EVT) { HAL_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: USERIAL_WAKEUP_EVT: %d", p_data->sigs); } else { HAL_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: unhandled userial evt: %i", evt); } }
/******************************************************************************* ** ** Function nfc_hal_prm_spd_handle_next_patch_start ** ** Description Handle start of next patch (for secure patch download) ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_spd_handle_next_patch_start (void) { UINT32 cur_patch_mask; UINT32 cur_patch_len; BOOLEAN found_patch_to_download = FALSE; while (!found_patch_to_download) { /* Get length of current patch */ cur_patch_len = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len; /* Check if this is a patch we need to download */ cur_patch_mask = ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode); if (nfc_hal_cb.prm.spd_patch_needed_mask & cur_patch_mask) { found_patch_to_download = TRUE; } else { /* Do not need to download this patch. Skip to next patch */ HAL_TRACE_DEBUG1 ("Skipping patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode); nfc_hal_cb.prm.spd_cur_patch_idx++; if (nfc_hal_cb.prm.spd_cur_patch_idx >= nfc_hal_cb.prm.spd_patch_count) { /* No more to download */ nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT); return; } else if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)) { /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch header */ (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH); return; } else { /* Patch in buffer. Skip over current patch. Check next patch */ nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) cur_patch_len; nfc_hal_cb.prm.cur_patch_offset += (UINT16) cur_patch_len; } } } /* Begin downloading patch */ HAL_TRACE_DEBUG1 ("Downloading patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode); nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_DOWNLOADING; nfc_hal_prm_spd_send_next_segment (); }
/******************************************************************************* ** ** Function nfc_hal_dm_send_bt_cmd ** ** Description Send BT message to NFCC while initializing BRCM NFCC ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_send_bt_cmd (const UINT8 *p_data, UINT16 len, tNFC_HAL_BTVSC_CPLT_CBACK *p_cback) { NFC_HDR *p_buf; HAL_TRACE_DEBUG1 ("nfc_hal_dm_send_bt_cmd (): nci_wait_rsp = 0x%x", nfc_hal_cb.ncit_cb.nci_wait_rsp); if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) { HAL_TRACE_ERROR0 ("nfc_hal_dm_send_bt_cmd(): no command window"); return; } if ((p_buf = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL) { nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_PROP; p_buf->offset = NFC_HAL_NCI_MSG_OFFSET_SIZE; p_buf->len = len; memcpy ((UINT8*) (p_buf + 1) + p_buf->offset, p_data, len); /* save the callback for NCI VSCs) */ nfc_hal_cb.ncit_cb.p_vsc_cback = (void *)p_cback; nfc_hal_cb.ncit_cb.p_pend_cmd = p_buf; if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE) { NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_CONTROL_DONE); nfc_hal_cb.p_stack_cback (HAL_NFC_REQUEST_CONTROL_EVT, HAL_NFC_STATUS_OK); return; } nfc_hal_dm_send_pend_cmd(); } }
/******************************************************************************* ** ** Function nfc_hal_dm_set_xtal_freq_index ** ** Description Set crystal frequency index ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_set_xtal_freq_index (void) { UINT8 nci_brcm_xtal_index_cmd[NCI_MSG_HDR_SIZE + NCI_PROP_PARAM_MAX_SIZE_XTAL_INDEX]; UINT8 *p; tNFC_HAL_XTAL_INDEX xtal_index; UINT16 xtal_freq; UINT8 cmd_len = NCI_PROP_PARAM_SIZE_XTAL_INDEX; extern UINT8 *p_nfc_hal_dm_xtal_params_cfg; HAL_TRACE_DEBUG1 ("nfc_hal_dm_set_xtal_freq_index (): brcm_hw_id = 0x%x", nfc_hal_cb.dev_cb.brcm_hw_id); xtal_index = nfc_hal_dm_get_xtal_index (nfc_hal_cb.dev_cb.brcm_hw_id, &xtal_freq); if ((xtal_index == NFC_HAL_XTAL_INDEX_SPECIAL) && (p_nfc_hal_dm_xtal_params_cfg)) { cmd_len += p_nfc_hal_dm_xtal_params_cfg[0]; /* [0] is the length of extra params */ } p = nci_brcm_xtal_index_cmd; UINT8_TO_STREAM (p, (NCI_MTS_CMD|NCI_GID_PROP)); UINT8_TO_STREAM (p, NCI_MSG_GET_XTAL_INDEX_FROM_DH); UINT8_TO_STREAM (p, cmd_len); UINT8_TO_STREAM (p, xtal_index); UINT16_TO_STREAM (p, xtal_freq); if (cmd_len > NCI_PROP_PARAM_SIZE_XTAL_INDEX) { memcpy (p, &p_nfc_hal_dm_xtal_params_cfg[1], p_nfc_hal_dm_xtal_params_cfg[0]); } NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_XTAL_SET); nfc_hal_dm_send_nci_cmd (nci_brcm_xtal_index_cmd, NCI_MSG_HDR_SIZE + cmd_len, NULL); }
/******************************************************************************* ** ** Function HAL_NfcDevInitDone ** ** Description Notify that pre-initialization of NFCC is complete ** ** Returns void ** *******************************************************************************/ void HAL_NfcPreInitDone (tHAL_NFC_STATUS status) { HAL_TRACE_DEBUG1 ("HAL_NfcPreInitDone () status=%d", status); if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) { NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); nfc_hal_main_pre_init_done (status); } }
/******************************************************************************* ** ** Function nfc_hal_main_pre_init_done ** ** Description notify complete of pre-initialization ** ** Returns nothing ** *******************************************************************************/ void nfc_hal_main_pre_init_done (tHAL_NFC_STATUS status) { HAL_TRACE_DEBUG1 ("nfc_hal_main_pre_init_done () status = %d", status); if (status != HAL_NFC_STATUS_OK) { nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); } /* Notify NFC Task the status of initialization */ nfc_hal_cb.p_stack_cback (HAL_NFC_OPEN_CPLT_EVT, status); }
/******************************************************************************* ** ** Function nfc_hal_dm_pre_set_mem_cback ** ** Description This is pre-set mem complete callback. ** ** Returns void ** *******************************************************************************/ static void nfc_hal_dm_pre_set_mem_cback (tNFC_HAL_BTVSC_CPLT *pData) { UINT8 status = pData->p_param_buf[0]; HAL_TRACE_DEBUG1 ("nfc_hal_dm_pre_set_mem_cback: %d", status); /* if it is completed */ if (status == HCI_SUCCESS) { if (!nfc_hal_dm_check_pre_set_mem()) { return; } } nfc_hal_dm_check_xtal(); }
/******************************************************************************* ** ** Function nfc_hal_dm_send_bt_cmd ** ** Description Send BT message to NFCC while initializing BRCM NFCC ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_send_bt_cmd (const UINT8 *p_data, UINT16 len, tNFC_HAL_BTVSC_CPLT_CBACK *p_cback) { NFC_HDR *p_buf; char buff[300]; char tmp[4]; buff[0] = 0; int i; HAL_TRACE_DEBUG1 ("nfc_hal_dm_send_bt_cmd (): nci_wait_rsp = 0x%x", nfc_hal_cb.ncit_cb.nci_wait_rsp); for (i = 0; i < len; i++) { sprintf (tmp, "%02x ", p_data[i]); strcat(buff, tmp); } HAL_TRACE_DEBUG2 ("nfc_hal_dm_send_bt_cmd (): HCI Write (%d bytes): %s", len, buff); if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) { HAL_TRACE_ERROR0 ("nfc_hal_dm_send_bt_cmd(): no command window"); return; } if ((p_buf = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL) { nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_PROP; p_buf->offset = NFC_HAL_NCI_MSG_OFFSET_SIZE; p_buf->len = len; memcpy ((UINT8*) (p_buf + 1) + p_buf->offset, p_data, len); /* save the callback for NCI VSCs) */ nfc_hal_cb.ncit_cb.p_vsc_cback = (void *)p_cback; nfc_hal_cb.ncit_cb.p_pend_cmd = p_buf; if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE) { NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_CONTROL_DONE); nfc_hal_cb.p_stack_cback (HAL_NFC_REQUEST_CONTROL_EVT, HAL_NFC_STATUS_OK); return; } nfc_hal_dm_send_pend_cmd(); } }
/******************************************************************************* ** ** Function nfc_hal_dm_set_nfc_wake ** ** Description Set NFC_WAKE line ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_set_nfc_wake (UINT8 cmd) { HAL_TRACE_DEBUG1 ("nfc_hal_dm_set_nfc_wake () %s", (cmd == NFC_HAL_ASSERT_NFC_WAKE ? "ASSERT" : "DEASSERT")); /* ** nfc_wake_active_mode cmd result of voltage on NFC_WAKE ** ** NFC_HAL_LP_ACTIVE_LOW (0) NFC_HAL_ASSERT_NFC_WAKE (0) pull down NFC_WAKE (GND) ** NFC_HAL_LP_ACTIVE_LOW (0) NFC_HAL_DEASSERT_NFC_WAKE (1) pull up NFC_WAKE (VCC) ** NFC_HAL_LP_ACTIVE_HIGH (1) NFC_HAL_ASSERT_NFC_WAKE (0) pull up NFC_WAKE (VCC) ** NFC_HAL_LP_ACTIVE_HIGH (1) NFC_HAL_DEASSERT_NFC_WAKE (1) pull down NFC_WAKE (GND) */ if (cmd == nfc_hal_cb.dev_cb.nfc_wake_active_mode) UPIO_Set (UPIO_GENERAL, NFC_HAL_LP_NFC_WAKE_GPIO, UPIO_OFF); /* pull down NFC_WAKE */ else UPIO_Set (UPIO_GENERAL, NFC_HAL_LP_NFC_WAKE_GPIO, UPIO_ON); /* pull up NFC_WAKE */ }
/******************************************************************************* ** ** Function: nfc_hal_dm_get_xtal_index ** ** Description: Return Xtal index and frequency ** ** Returns: tNFC_HAL_XTAL_INDEX ** *******************************************************************************/ tNFC_HAL_XTAL_INDEX nfc_hal_dm_get_xtal_index (UINT32 brcm_hw_id, UINT16 *p_xtal_freq) { UINT8 xx; HAL_TRACE_DEBUG1("nfc_hal_dm_get_xtal_index() brcm_hw_id:0x%x", brcm_hw_id); for (xx = 0; xx < nfc_post_reset_cb.dev_init_config.num_xtal_cfg; xx++) { if ((brcm_hw_id & BRCM_NFC_GEN_MASK) == nfc_post_reset_cb.dev_init_config.xtal_cfg[xx].brcm_hw_id) { *p_xtal_freq = nfc_post_reset_cb.dev_init_config.xtal_cfg[xx].xtal_freq; return (nfc_post_reset_cb.dev_init_config.xtal_cfg[xx].xtal_index); } } /* if not found */ *p_xtal_freq = 0; return (NFC_HAL_XTAL_INDEX_MAX); }
/******************************************************************************* ** ** Function HAL_NfcReInit ** ** Description This function is called to restart initialization after REG_PU ** toggled because of failure to detect NVM type or download patchram. ** ** Note This function should be called only during the HAL init process ** ** Returns HAL_NFC_STATUS_OK if successfully initiated ** HAL_NFC_STATUS_FAILED otherwise ** *******************************************************************************/ tHAL_NFC_STATUS HAL_NfcReInit (void) { tHAL_NFC_STATUS status = HAL_NFC_STATUS_FAILED; HAL_TRACE_DEBUG1 ("HAL_NfcReInit () init st=0x%x", nfc_hal_cb.dev_cb.initializing_state); if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) { { /* Wait for NFCC to enable - Core reset notification */ NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_NFCC_ENABLE); /* NFCC Enable timeout */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_NFCC_ENABLE, ((p_nfc_hal_cfg->nfc_hal_nfcc_enable_timeout)*QUICK_TIMER_TICKS_PER_SEC)/1000); } status = HAL_NFC_STATUS_OK; } return status; }
/******************************************************************************* ** ** Function nfc_hal_dm_send_nci_cmd ** ** Description Send NCI command to NFCC while initializing BRCM NFCC ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_send_nci_cmd (const UINT8 *p_data, UINT16 len, tNFC_HAL_NCI_CBACK *p_cback) { NFC_HDR *p_buf; UINT8 *ps; HAL_TRACE_DEBUG1 ("nfc_hal_dm_send_nci_cmd (): nci_wait_rsp = 0x%x", nfc_hal_cb.ncit_cb.nci_wait_rsp); if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) { HAL_TRACE_ERROR0 ("nfc_hal_dm_send_nci_cmd(): no command window"); return; } if ((p_buf = (NFC_HDR *)GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL) { nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_VSC; p_buf->offset = NFC_HAL_NCI_MSG_OFFSET_SIZE; p_buf->event = NFC_HAL_EVT_TO_NFC_NCI; p_buf->len = len; memcpy ((UINT8*) (p_buf + 1) + p_buf->offset, p_data, len); /* Keep a copy of the command and send to NCI transport */ /* save the message header to double check the response */ ps = (UINT8 *)(p_buf + 1) + p_buf->offset; memcpy(nfc_hal_cb.ncit_cb.last_hdr, ps, NFC_HAL_SAVED_HDR_SIZE); memcpy(nfc_hal_cb.ncit_cb.last_cmd, ps + NCI_MSG_HDR_SIZE, NFC_HAL_SAVED_CMD_SIZE); /* save the callback for NCI VSCs */ nfc_hal_cb.ncit_cb.p_vsc_cback = (void *)p_cback; nfc_hal_nci_send_cmd (p_buf); /* start NFC command-timeout timer */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer, (UINT16)(NFC_HAL_TTYPE_NCI_WAIT_RSP), ((UINT32) NFC_HAL_CMD_TOUT) * QUICK_TIMER_TICKS_PER_SEC / 1000); } }
/******************************************************************************* ** ** Function nfc_hal_dm_set_xtal_freq_index ** ** Description Set crystal frequency index ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_set_xtal_freq_index (void) { UINT8 nci_brcm_xtal_index_cmd[NCI_MSG_HDR_SIZE + NCI_PROP_PARAM_SIZE_XTAL_INDEX]; UINT8 *p; tNFC_HAL_XTAL_INDEX xtal_index; UINT16 xtal_freq; HAL_TRACE_DEBUG1 ("nfc_hal_dm_set_xtal_freq_index (): brcm_hw_id = 0x%x", nfc_hal_cb.dev_cb.brcm_hw_id); xtal_index = nfc_hal_dm_get_xtal_index (nfc_hal_cb.dev_cb.brcm_hw_id, &xtal_freq); p = nci_brcm_xtal_index_cmd; UINT8_TO_STREAM (p, (NCI_MTS_CMD|NCI_GID_PROP)); UINT8_TO_STREAM (p, NCI_MSG_GET_XTAL_INDEX_FROM_DH); UINT8_TO_STREAM (p, NCI_PROP_PARAM_SIZE_XTAL_INDEX); UINT8_TO_STREAM (p, xtal_index); UINT16_TO_STREAM (p, xtal_freq); NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_XTAL_SET); nfc_hal_dm_send_nci_cmd (nci_brcm_xtal_index_cmd, NCI_MSG_HDR_SIZE + NCI_PROP_PARAM_SIZE_XTAL_INDEX, NULL); }
/******************************************************************************* ** ** Function nfc_hal_main_timeout_cback ** ** Description callback function for timeout ** ** Returns void ** *******************************************************************************/ static void nfc_hal_main_timeout_cback (void *p_tle) { TIMER_LIST_ENT *p_tlent = (TIMER_LIST_ENT *) p_tle; HAL_TRACE_DEBUG0 ("nfc_hal_main_timeout_cback ()"); switch (p_tlent->event) { case NFC_HAL_TTYPE_POWER_CYCLE: nfc_hal_main_open_transport (); break; case NFC_HAL_TTYPE_NFCC_ENABLE: /* NFCC should have enabled now, notify transport openned */ nfc_hal_dm_pre_init_nfcc (); break; default: HAL_TRACE_DEBUG1 ("nfc_hal_main_timeout_cback: unhandled timer event (0x%04x)", p_tlent->event); break; } }
/******************************************************************************* ** ** Function nfc_hal_dm_power_mode_execute ** ** Description If snooze mode is enabled in full power mode, ** Assert NFC_WAKE before sending data ** Deassert NFC_WAKE when idle timer expires ** ** Returns TRUE if DH can send data to NFCC ** *******************************************************************************/ BOOLEAN nfc_hal_dm_power_mode_execute (tNFC_HAL_LP_EVT event) { BOOLEAN send_to_nfcc = FALSE; HAL_TRACE_DEBUG1 ("nfc_hal_dm_power_mode_execute () event = %d", event); if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) { if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) { /* if any transport activity */ if ( (event == NFC_HAL_LP_TX_DATA_EVT) ||(event == NFC_HAL_LP_RX_DATA_EVT) ) { /* if idle timer is not running */ if (nfc_hal_cb.dev_cb.lp_timer.in_use == FALSE) { nfc_hal_dm_set_nfc_wake (NFC_HAL_ASSERT_NFC_WAKE); } /* start or extend idle timer */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.dev_cb.lp_timer, 0x00, ((UINT32) NFC_HAL_LP_IDLE_TIMEOUT) * QUICK_TIMER_TICKS_PER_SEC / 1000); } else if (event == NFC_HAL_LP_TIMEOUT_EVT) { /* let NFCC go to snooze mode */ nfc_hal_dm_set_nfc_wake (NFC_HAL_DEASSERT_NFC_WAKE); } } send_to_nfcc = TRUE; } return (send_to_nfcc); }
/******************************************************************************* ** ** Function nfc_hal_prm_nci_command_complete_cback ** ** Description Callback for NCI vendor specific command complete ** (for secure patch download) ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_nci_command_complete_cback (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data) { UINT8 status, u8; UINT8 *p; UINT32 post_signature_delay; NFC_HAL_PRM_STATE ("nfc_hal_prm_nci_command_complete_cback"); /* Stop the command-timeout timer */ nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer); /* Skip over NCI header */ p = p_data + NCI_MSG_HDR_SIZE; /* Handle SECURE_PATCH_DOWNLOAD Rsp */ if (event == NFC_VS_SEC_PATCH_DOWNLOAD_EVT) { /* Status and error code */ STREAM_TO_UINT8 (status, p); STREAM_TO_UINT8 (u8, p); if (status != NCI_STATUS_OK) { #if (NFC_HAL_TRACE_VERBOSE == TRUE) HAL_TRACE_ERROR2 ("Patch download failed, reason code=0x%X (%s)", status, nfc_hal_prm_spd_status_str (status)); #else HAL_TRACE_ERROR1 ("Patch download failed, reason code=0x%X", status); #endif /* Notify application */ nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT); return; } /* If last segment (SIGNATURE) sent */ if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SIGNATURE_SENT) { /* Wait for authentication complete (SECURE_PATCH_DOWNLOAD NTF), including time to commit to NVM (for BCM43341B0) */ int auth_delay = NFC_HAL_PRM_SPD_TOUT; if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3)) { /* XXX maco only wait 30 seconds for B4+ revisions to avoid watchdog timeouts */ auth_delay = NFC_HAL_PRM_COMMIT_DELAY; } nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTHENTICATING; nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00, (auth_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000); return; } /* Download next segment */ else if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF) { /* If patch is in a buffer, get next patch from buffer */ nfc_hal_prm_spd_send_next_segment (); } else { /* Notify adaptation layer to get next patch segment (via HAL_NfcPrmDownloadContinue) */ (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_CONTINUE_EVT); } } /* Handle SECURE_PATCH_DOWNLOAD NTF */ else if (event == NFC_VS_SEC_PATCH_AUTH_EVT) { HAL_TRACE_DEBUG1 ("prm flags:0x%x.", nfc_hal_cb.prm.flags); /* Status and error code */ STREAM_TO_UINT8 (status, p); STREAM_TO_UINT8 (u8, p); /* Sanity check - should only get this NTF while in AUTHENTICATING stage */ if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTHENTICATING) { if (status != NCI_STATUS_OK) { HAL_TRACE_ERROR0 ("Patch authentication failed"); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_BAD_SIGNATURE_EVT); return; } #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE)) if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED) { HAL_TRACE_DEBUG1 ("PreI2C patch downloaded...waiting %i ms for NFCC to reboot.", nfc_hal_cb.prm_i2c.prei2c_delay); /* Restore pointers to patchfile */ nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED; nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm.p_spd_patch; nfc_hal_cb.prm.cur_patch_offset = nfc_hal_cb.prm.spd_patch_offset; nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm.spd_patch_len_remaining; /* Resume normal patch download */ nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER; nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT; /* Post PreI2C delay */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00, (nfc_hal_cb.prm_i2c.prei2c_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000); return; } #endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */ /* Wait for NFCC to save the patch to NVM */ if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3)) { /* 20791B4 or newer - wait for RESET_NTF; including time to commit to NVM (for BCM20791B4+) */ post_signature_delay = NFC_HAL_PRM_COMMIT_DELAY; HAL_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for RESET NTF...", post_signature_delay); } else if (nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_NO_NVM) { /* No NVM. Wait for NFCC to restart */ post_signature_delay = NFC_HAL_PRM_END_DELAY; HAL_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NFCC to restart...", post_signature_delay); } else { /* Wait for NFCC to save the patch to NVM (need about 1 ms per byte) */ post_signature_delay = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len; if (post_signature_delay < nfc_hal_cb.prm.patchram_delay) post_signature_delay = nfc_hal_cb.prm.patchram_delay; HAL_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NVM update to complete...", post_signature_delay); } nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTH_DONE; nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00, (post_signature_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000); } else { HAL_TRACE_ERROR0 ("Got unexpected SECURE_PATCH_DOWNLOAD NTF"); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT); } } /* Handle NCI_MSG_GET_PATCH_VERSION RSP */ else if (event == NFC_VS_GET_PATCH_VERSION_EVT) { nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT); } else { /* Invalid response from NFCC during patch download */ HAL_TRACE_ERROR1 ("Invalid response from NFCC during patch download (opcode=0x%02X)", event); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT); } NFC_HAL_PRM_STATE ("prm_nci_command_complete_cback"); }
/******************************************************************************* ** ** Function nfc_hal_dm_config_nfcc ** ** Description Send VS config before NFA start-up ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_config_nfcc (void) { HAL_TRACE_DEBUG1 ("nfc_hal_dm_config_nfcc (): next_dm_config = %d", nfc_hal_cb.dev_cb.next_dm_config); if ((p_nfc_hal_dm_lptd_cfg[0]) && (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_LPTD)) { nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_PLL_325; if (nfc_hal_dm_set_config (p_nfc_hal_dm_lptd_cfg[0], &p_nfc_hal_dm_lptd_cfg[1], nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) { return; } else { NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_FAILED); return; } } if ((p_nfc_hal_dm_pll_325_cfg) && (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_PLL_325)) { nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_START_UP; if (nfc_hal_dm_set_config (NFC_HAL_PLL_325_SETCONFIG_PARAM_LEN, p_nfc_hal_dm_pll_325_cfg, nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) { return; } else { NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_FAILED); return; } } if ((p_nfc_hal_dm_start_up_cfg[0]) && (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_START_UP)) { nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_I93_DATA_RATE; if (nfc_hal_dm_set_config (p_nfc_hal_dm_start_up_cfg[0], &p_nfc_hal_dm_start_up_cfg[1], nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) { return; } else { NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_FAILED); return; } } #if (NFC_HAL_I93_FLAG_DATA_RATE == NFC_HAL_I93_FLAG_DATA_RATE_HIGH) if (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_I93_DATA_RATE) { nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_FW_FSM; if (nfc_hal_dm_set_config (NFC_HAL_I93_RW_CFG_LEN, nfc_hal_dm_i93_rw_cfg, nfc_hal_dm_config_nfcc_cback) == HAL_NFC_STATUS_OK) { return; } else { NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_FAILED); return; } } #endif /* FW FSM is disabled as default in NFCC */ if (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_FW_FSM) { nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_START_UP_VSC; nfc_hal_dm_set_fw_fsm (NFC_HAL_DM_MULTI_TECH_RESP, nfc_hal_dm_config_nfcc_cback); return; } if (nfc_hal_cb.dev_cb.next_dm_config <= NFC_HAL_DM_CONFIG_START_UP_VSC) { if (p_nfc_hal_dm_start_up_vsc_cfg && *p_nfc_hal_dm_start_up_vsc_cfg) { nfc_hal_dm_send_startup_vsc (); return; } } /* nothing to config */ nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_NONE; nfc_hal_dm_config_nfcc_cback (0, 0, NULL); }
/******************************************************************************* ** ** Function nfc_hal_main_send_message ** ** Description This function is calledto send an NCI message. ** ** Returns void ** *******************************************************************************/ static void nfc_hal_main_send_message (NFC_HDR *p_msg) { #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) UINT8 cid, pbf; UINT16 data_len; #endif UINT8 *ps, *pp; UINT16 len = p_msg->len; #ifdef DISP_NCI UINT8 delta; #endif HAL_TRACE_DEBUG1 ("nfc_hal_main_send_message() ls:0x%x", p_msg->layer_specific); if ( (p_msg->layer_specific == NFC_HAL_WAIT_RSP_CMD) ||(p_msg->layer_specific == NFC_HAL_WAIT_RSP_VSC) ) { nfc_hal_nci_send_cmd (p_msg); } else { /* NFC task has fragmented the data packet to the appropriate size * and data credit is available; just send it */ /* add NCI packet type in front of message */ nfc_hal_nci_add_nfc_pkt_type (p_msg); /* send this packet to transport */ ps = (UINT8 *) (p_msg + 1) + p_msg->offset; pp = ps + 1; #ifdef DISP_NCI delta = p_msg->len - len; DISP_NCI (ps + delta, (UINT16) (p_msg->len - delta), FALSE); #endif #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) if (nfc_hal_cb.hci_cb.hcp_conn_id) { NCI_DATA_PRS_HDR(pp, pbf, cid, data_len); if (cid == nfc_hal_cb.hci_cb.hcp_conn_id) { if (nfc_hal_hci_handle_hcp_pkt_to_hc (pp)) { HAL_TRACE_DEBUG0 ("nfc_hal_main_send_message() - Drop rsp to Fake cmd, Fake credit ntf"); GKI_freebuf (p_msg); nfc_hal_send_credit_ntf_for_cid (cid); return; } } } #endif /* check low power mode state */ if (nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT)) { USERIAL_Write (USERIAL_NFC_PORT, ps, p_msg->len); } else { HAL_TRACE_ERROR0 ("nfc_hal_main_send_message(): drop data in low power mode"); } GKI_freebuf (p_msg); } }
/******************************************************************************* ** ** Function nfc_hal_dm_proc_msg_during_init ** ** Description Process NCI message while initializing NFCC ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_proc_msg_during_init (NFC_HDR *p_msg) { UINT8 *p; UINT8 reset_reason, reset_type; UINT8 mt, pbf, gid, op_code; UINT8 *p_old, old_gid, old_oid, old_mt; UINT8 u8; tNFC_HAL_NCI_CBACK *p_cback = NULL; UINT8 chipverlen; UINT8 chipverstr[NCI_SPD_HEADER_CHIPVER_LEN]; UINT32 hw_id = 0; HAL_TRACE_DEBUG1 ("nfc_hal_dm_proc_msg_during_init(): init state:%d", nfc_hal_cb.dev_cb.initializing_state); p = (UINT8 *) (p_msg + 1) + p_msg->offset; NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); NCI_MSG_PRS_HDR1 (p, op_code); /* check if waiting for this response */ if ( (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_CMD) ||(nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_VSC) ) { if (mt == NCI_MT_RSP) { p_old = nfc_hal_cb.ncit_cb.last_hdr; NCI_MSG_PRS_HDR0 (p_old, old_mt, pbf, old_gid); old_oid = ((*p_old) & NCI_OID_MASK); /* make sure this is the RSP we are waiting for before updating the command window */ if ((old_gid == gid) && (old_oid == op_code)) { nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; p_cback = (tNFC_HAL_NCI_CBACK *)nfc_hal_cb.ncit_cb.p_vsc_cback; nfc_hal_cb.ncit_cb.p_vsc_cback = NULL; nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); } } } if (gid == NCI_GID_CORE) { if (op_code == NCI_MSG_CORE_RESET) { if (mt == NCI_MT_NTF) { if ( (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_ENABLE) ||(nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_POST_XTAL_SET) ) { /* ** Core reset ntf in the following cases; ** 1) after power up (raising REG_PU) ** 2) after setting xtal index ** Start pre-initializing NFCC */ nfc_hal_main_stop_quick_timer (&nfc_hal_cb.timer); nfc_hal_dm_pre_init_nfcc (); } else { /* Core reset ntf after post-patch download, Call reset notification callback */ p++; /* Skip over param len */ STREAM_TO_UINT8 (reset_reason, p); STREAM_TO_UINT8 (reset_type, p); nfc_hal_prm_spd_reset_ntf (reset_reason, reset_type); } } } else if (p_cback) { (*p_cback) ((tNFC_HAL_NCI_EVT) (op_code), p_msg->len, (UINT8 *) (p_msg + 1) + p_msg->offset); } } else if (gid == NCI_GID_PROP) /* this is for download patch */ { if (mt == NCI_MT_NTF) op_code |= NCI_NTF_BIT; else op_code |= NCI_RSP_BIT; if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_XTAL_SET) { if (op_code == (NCI_RSP_BIT|NCI_MSG_GET_XTAL_INDEX_FROM_DH)) { /* start timer in case that NFCC doesn't send RESET NTF after loading patch from NVM */ NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_POST_XTAL_SET); nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_NFCC_ENABLE, ((p_nfc_hal_cfg->nfc_hal_post_xtal_timeout)*QUICK_TIMER_TICKS_PER_SEC)/1000); } } else if ( (op_code == NFC_VS_GET_BUILD_INFO_EVT) &&(nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_BUILD_INFO) ) { p += NCI_BUILD_INFO_OFFSET_HWID; STREAM_TO_UINT32 (hw_id, p); nfc_hal_cb.dev_cb.brcm_hw_id = nfc_hal_dm_adjust_hw_id (hw_id); HAL_TRACE_DEBUG2 ("brcm_hw_id: 0x%x -> 0x%x", hw_id, nfc_hal_cb.dev_cb.brcm_hw_id); STREAM_TO_UINT8 (chipverlen, p); memset (chipverstr, 0, NCI_SPD_HEADER_CHIPVER_LEN); STREAM_TO_ARRAY (chipverstr, p, chipverlen); nfc_hal_hci_handle_build_info (chipverlen, chipverstr); nfc_hal_cb.pre_set_mem_idx = 0; if (!nfc_hal_dm_check_pre_set_mem()) { /* pre-set mem started */ return; } nfc_hal_dm_check_xtal(); } else if ( (op_code == NFC_VS_GET_PATCH_VERSION_EVT) &&(nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PATCH_INFO) ) { /* Store NVM info to control block */ /* Skip over rsp len */ p++; /* Get project id */ STREAM_TO_UINT16 (nfc_hal_cb.nvm_cb.project_id, p); /* RFU */ p++; /* Get chip version string */ STREAM_TO_UINT8 (u8, p); if (u8 > NFC_HAL_PRM_MAX_CHIP_VER_LEN) u8 = NFC_HAL_PRM_MAX_CHIP_VER_LEN; memcpy (nfc_hal_cb.nvm_cb.chip_ver, p, u8); p += NCI_PATCH_INFO_VERSION_LEN; /* Get major/minor version */ STREAM_TO_UINT16 (nfc_hal_cb.nvm_cb.ver_major, p); STREAM_TO_UINT16 (nfc_hal_cb.nvm_cb.ver_minor, p); /* Skip over max_size and patch_max_size */ p += 4; /* Get current lpm patch size */ STREAM_TO_UINT16 (nfc_hal_cb.nvm_cb.lpm_size, p); STREAM_TO_UINT16 (nfc_hal_cb.nvm_cb.fpm_size, p); /* clear all flags which may be set during previous initialization */ nfc_hal_cb.nvm_cb.flags = 0; /* Set patch present flag */ if ((nfc_hal_cb.nvm_cb.fpm_size) || (nfc_hal_cb.nvm_cb.lpm_size)) nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_PATCH_PRESENT; /* LPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is present in nvm) */ STREAM_TO_UINT8 (u8, p); if (u8) { /* LPM patch in NVM fails CRC check */ nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_LPM_BAD; } /* FPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is present in nvm) */ STREAM_TO_UINT8 (u8, p); if (u8) { /* FPM patch in NVM fails CRC check */ nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_FPM_BAD; } /* Check if downloading patch to RAM only (no NVM) */ STREAM_TO_UINT8 (nfc_hal_cb.nvm_cb.nvm_type, p); if (nfc_hal_cb.nvm_cb.nvm_type == NCI_SPD_NVM_TYPE_NONE) { nfc_hal_cb.nvm_cb.flags |= NFC_HAL_NVM_FLAGS_NO_NVM; } /* let platform update baudrate or download patch */ NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_APP_COMPLETE); nfc_hal_post_reset_init (nfc_hal_cb.dev_cb.brcm_hw_id, nfc_hal_cb.nvm_cb.nvm_type); } else if (p_cback) { (*p_cback) ((tNFC_HAL_NCI_EVT) (op_code), p_msg->len, (UINT8 *) (p_msg + 1) + p_msg->offset); } else if (op_code == NFC_VS_SEC_PATCH_AUTH_EVT) { HAL_TRACE_DEBUG0 ("signature!!"); nfc_hal_prm_nci_command_complete_cback ((tNFC_HAL_NCI_EVT) (op_code), p_msg->len, (UINT8 *) (p_msg + 1) + p_msg->offset); } } }