/******************************************************************************* ** ** Function nfc_hal_prm_spd_reset_ntf ** ** Description Received RESET NTF from NFCC, indicating it has completed ** reset after patch download. ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_spd_reset_ntf (UINT8 reset_reason, UINT8 reset_type) { /* Check if we were expecting a RESET NTF */ if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE) { HAL_TRACE_DEBUG2 ("Received RESET NTF after patch download (reset_reason=%i, reset_type=%i)", reset_reason, reset_type); /* Stop waiting for RESET NTF */ nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer); { /* Continue with patch download */ nfc_hal_prm_nfcc_ready_to_continue (); } } else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER) { HAL_TRACE_DEBUG0 ("Received RESET NTF after pre-I2C patch download. Proceeding with patch download..."); /* Stop waiting for RESET NTF */ nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer); nfc_hal_prm_spd_handle_next_patch_start (); } else { HAL_TRACE_ERROR2 ("Received unexpected RESET NTF (reset_reason=%i, reset_type=%i)", reset_reason, reset_type); } }
/******************************************************************************* ** ** Function nfc_hal_dm_send_startup_vsc ** ** Description Send VS command before NFA start-up ** ** Returns None ** *******************************************************************************/ void nfc_hal_dm_send_startup_vsc (void) { UINT8 *p, *p_end; UINT16 len; HAL_TRACE_DEBUG0 ("nfc_hal_dm_send_startup_vsc ()"); /* VSC must have NCI header at least */ if (nfc_hal_cb.dev_cb.next_startup_vsc + NCI_MSG_HDR_SIZE - 1 <= *p_nfc_hal_dm_start_up_vsc_cfg) { p = p_nfc_hal_dm_start_up_vsc_cfg + nfc_hal_cb.dev_cb.next_startup_vsc; len = *(p + 2); p_end = p + NCI_MSG_HDR_SIZE - 1 + len; if (p_end <= p_nfc_hal_dm_start_up_vsc_cfg + *p_nfc_hal_dm_start_up_vsc_cfg) { /* move to next VSC */ nfc_hal_cb.dev_cb.next_startup_vsc += NCI_MSG_HDR_SIZE + len; /* if this is last VSC */ if (p_end == p_nfc_hal_dm_start_up_vsc_cfg + *p_nfc_hal_dm_start_up_vsc_cfg) nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_NONE; nfc_hal_dm_send_nci_cmd (p, (UINT16)(NCI_MSG_HDR_SIZE + len), nfc_hal_dm_config_nfcc_cback); return; } } HAL_TRACE_ERROR0 ("nfc_hal_dm_send_startup_vsc (): Bad start-up VSC"); 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); }
/******************************************************************************* ** ** Function nfc_hal_dm_shutting_down_nfcc ** ** Description This function initializes Broadcom specific control blocks for ** NCI transport ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_shutting_down_nfcc (void) { HAL_TRACE_DEBUG0 ("nfc_hal_dm_shutting_down_nfcc ()"); nfc_hal_cb.dev_cb.initializing_state = NFC_HAL_INIT_STATE_CLOSING; /* reset low power mode variables */ if ( (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) &&(nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) ) { nfc_hal_dm_set_nfc_wake (NFC_HAL_ASSERT_NFC_WAKE); } nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; nfc_hal_cb.dev_cb.power_mode = NFC_HAL_POWER_MODE_FULL; nfc_hal_cb.dev_cb.snooze_mode = NFC_HAL_LP_SNOOZE_MODE_NONE; /* Stop all timers */ nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); nfc_hal_main_stop_quick_timer (&nfc_hal_cb.dev_cb.lp_timer); nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer); #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) nfc_hal_cb.hci_cb.hcp_conn_id = 0; nfc_hal_main_stop_quick_timer (&nfc_hal_cb.hci_cb.hci_timer); #endif nfc_hal_main_stop_quick_timer (&nfc_hal_cb.timer); }
/******************************************************************************* ** ** Function nfc_hal_prm_process_timeout ** ** Description Process timer expireation for patch download ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_process_timeout (void *p_tle) { NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout"); if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE) { if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3)) { /* Timeout waiting for RESET NTF after signature sent */ HAL_TRACE_ERROR0 ("Timeout waiting for RESET NTF after patch download"); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT); } else { nfc_hal_prm_nfcc_ready_to_continue (); } } else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER) { HAL_TRACE_DEBUG0 ("Delay after PreI2C patch download...proceeding to download firmware patch"); nfc_hal_prm_spd_handle_next_patch_start (); } else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_W4_GET_VERSION) { HAL_TRACE_DEBUG0 ("get patch version timeout???"); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT); } else { HAL_TRACE_ERROR1 ("Patch download: command timeout (state=%i)", nfc_hal_cb.prm.state); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT); } NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout"); }
/******************************************************************************* ** ** Function nfc_hal_dm_init ** ** Description This function initializes Broadcom specific control blocks for ** NCI transport ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_init (void) { HAL_TRACE_DEBUG0 ("nfc_hal_dm_init ()"); nfc_hal_cb.dev_cb.lp_timer.p_cback = nci_brcm_lp_timeout_cback; nfc_hal_cb.ncit_cb.nci_wait_rsp_timer.p_cback = nfc_hal_nci_cmd_timeout_cback; nfc_hal_cb.hci_cb.hci_timer.p_cback = nfc_hal_hci_timeout_cback; nfc_hal_cb.pre_discover_done = FALSE; nfc_post_reset_cb.spd_nvm_detection_cur_count = 0; nfc_post_reset_cb.spd_skip_on_power_cycle = FALSE; }
/******************************************************************************* ** ** Function nfc_hal_dm_init ** ** Description This function initializes Broadcom specific control blocks for ** NCI transport ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_init (void) { HAL_TRACE_DEBUG0 ("nfc_hal_dm_init ()"); nfc_hal_cb.dev_cb.lp_timer.p_cback = nci_brcm_lp_timeout_cback; nfc_hal_cb.ncit_cb.nci_wait_rsp_timer.p_cback = nfc_hal_nci_cmd_timeout_cback; #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) nfc_hal_cb.hci_cb.hci_timer.p_cback = nfc_hal_hci_timeout_cback; #endif nfc_hal_cb.pre_discover_done = FALSE; nfc_post_reset_cb.spd_nvm_detection_cur_count = 0; nfc_post_reset_cb.spd_skip_on_power_cycle = FALSE; }
/******************************************************************************* ** ** Function nfc_hal_dm_pre_init_nfcc ** ** Description This function initializes Broadcom specific control blocks for ** NCI transport ** ** Returns void ** *******************************************************************************/ void nfc_hal_dm_pre_init_nfcc (void) { HAL_TRACE_DEBUG0 ("nfc_hal_dm_pre_init_nfcc ()"); /* if it was waiting for core reset notification after raising REG_PU */ if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_ENABLE) { nfc_hal_dm_send_get_build_info_cmd (); } /* if it was waiting for core reset notification after setting Xtal */ else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_POST_XTAL_SET) { { /* Core reset ntf after xtal setting indicating NFCC loaded patch from NVM */ NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_PATCH_INFO); nfc_hal_dm_send_nci_cmd (nfc_hal_dm_get_patch_version_cmd, NCI_MSG_HDR_SIZE, NULL); } } }
/******************************************************************************* ** ** Function nfc_hal_prm_nfcc_ready_to_continue ** ** Description Continue to download patch or notify application completition ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_nfcc_ready_to_continue (void) { UINT8 get_patch_version_cmd [NCI_MSG_HDR_SIZE] = { NCI_MTS_CMD|NCI_GID_PROP, NCI_MSG_GET_PATCH_VERSION, 0x00 }; /* Clear the bit for the patch we just downloaded */ nfc_hal_cb.prm.spd_patch_needed_mask &= ~ ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode); /* Check if another patch to download */ nfc_hal_cb.prm.spd_cur_patch_idx++; if ((nfc_hal_cb.prm.spd_patch_needed_mask) && (nfc_hal_cb.prm.spd_cur_patch_idx < nfc_hal_cb.prm.spd_patch_count)) { nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER; nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT; 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_handle_next_patch_start (); } else { /* Notify adaptation layer to get next patch header (via HAL_NfcPrmDownloadContinue) */ (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH); } } else { /* Done downloading */ HAL_TRACE_DEBUG0 ("Patch downloaded and authenticated. Get new patch version."); /* add get patch info again to verify the effective FW version */ nfc_hal_dm_send_nci_cmd (get_patch_version_cmd, NCI_MSG_HDR_SIZE, nfc_hal_prm_nci_command_complete_cback); nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_W4_GET_VERSION; } }
/******************************************************************************* ** ** 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_prm_spd_check_version ** ** Description Check patchfile version with current downloaded version ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_spd_check_version (void) { UINT8 *p, *p_start, i; UINT32 nvm_patch_present_mask = 0; UINT32 patchfile_patch_present_mask; UINT16 patchfile_project_id = 0; UINT16 patchfile_ver_major = 0; UINT16 patchfile_ver_minor = 0; UINT16 patchfile_patchsize; UINT8 return_code = NFC_HAL_PRM_COMPLETE_EVT; /* Initialize patchfile offset pointers */ p = p_start = NULL; patchfile_patchsize = 0; /* the good patches in NVM */ if (nfc_hal_cb.nvm_cb.lpm_size && !(nfc_hal_cb.nvm_cb.flags & (NFC_HAL_NVM_FLAGS_LPM_BAD))) nvm_patch_present_mask |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_LPM); if (nfc_hal_cb.nvm_cb.fpm_size && !(nfc_hal_cb.nvm_cb.flags & (NFC_HAL_NVM_FLAGS_FPM_BAD))) nvm_patch_present_mask |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_FPM); /* Get patchfile version */ if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN) { /* Parse patchfile header */ p = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data; p_start = p; STREAM_TO_UINT16 (patchfile_project_id, p); STREAM_TO_UINT16 (patchfile_ver_major, p); STREAM_TO_UINT16 (patchfile_ver_minor, p); /* RFU */ p++; /* Check how many patches are in the patch file */ STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_count, p); if (nfc_hal_cb.prm.spd_patch_count > NFC_HAL_PRM_MAX_PATCH_COUNT) { HAL_TRACE_ERROR2 ("Unsupported patchfile (number of patches (%i) exceeds maximum (%i)", nfc_hal_cb.prm.spd_patch_count, NFC_HAL_PRM_MAX_PATCH_COUNT); } /* Mask of patches that are present in the patchfile */ patchfile_patch_present_mask = 0; /* Get lengths for each patch */ for (i = 0; i < nfc_hal_cb.prm.spd_patch_count; i++) { /* Get power mode for this patch */ STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_desc[i].power_mode, p); /* Update mask of power-modes present in the patchfile */ patchfile_patch_present_mask |= ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[i].power_mode); /* Get length of patch */ STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_patch_desc[i].len, p); /* Add total size of patches */ patchfile_patchsize += nfc_hal_cb.prm.spd_patch_desc[i].len; /* 5 byte RFU */ p += 5; } /* Adjust offset to after the patch file header */ nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start); /* Bytes of patchfile transmitted/processed so far */ nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start); /* Adjust size of patchfile */ HAL_TRACE_DEBUG4 ("NVM Patch info: flags=0x%04x, Ver=%i.%i, PatchMask=0x%08x", nfc_hal_cb.nvm_cb.flags, nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor, nvm_patch_present_mask ); HAL_TRACE_DEBUG6 ("Patchfile info: ProjID=0x%04x, Ver=%i.%i, Num patches=%i, PatchMask=0x%08x, PatchSize=%i", patchfile_project_id, patchfile_ver_major, patchfile_ver_minor, nfc_hal_cb.prm.spd_patch_count, patchfile_patch_present_mask, patchfile_patchsize); /********************************************************************* * Version check of patchfile against NVM ******************************************************************** /* Download the patchfile if no patches in NVM */ if ((nfc_hal_cb.nvm_cb.project_id == 0) || !(nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_PATCH_PRESENT)) { /* No patch in NVM, need to download all */ nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask; HAL_TRACE_DEBUG2 ("No previous patch detected. Downloading patch %i.%i", patchfile_ver_major, patchfile_ver_minor); } /* Skip download if project ID of patchfile does not match NVM */ else if (nfc_hal_cb.nvm_cb.project_id != patchfile_project_id) { /* Project IDs mismatch */ HAL_TRACE_DEBUG2 ("Patch download skipped: Mismatched Project ID (NVM ProjId: 0x%04x, Patchfile ProjId: 0x%04x)", nfc_hal_cb.nvm_cb.project_id, patchfile_project_id); return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT; } /* Skip download if version of patchfile is equal to version in NVM */ /* and patches of the power modes are the same as the good patches in NVM */ else if ( (nfc_hal_cb.nvm_cb.ver_major == patchfile_ver_major) &&(nfc_hal_cb.nvm_cb.ver_minor == patchfile_ver_minor) &&((nvm_patch_present_mask | patchfile_patch_present_mask) == nvm_patch_present_mask) ) /* if the NVM patch include all the patched in file */ { HAL_TRACE_DEBUG2 ("Patch download skipped. NVM patch (version %i.%i) is the same than the patchfile ", nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor); return_code = NFC_HAL_PRM_COMPLETE_EVT; } /* Remaining cases: Download all patches in the patchfile */ else { nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask; HAL_TRACE_DEBUG4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...", patchfile_ver_major, patchfile_ver_minor, nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor); } } else { /* Invalid patch file header */ HAL_TRACE_ERROR0 ("Invalid patch file header."); return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT; } /* If we need to download anything, get the first patch to download */ if (nfc_hal_cb.prm.spd_patch_needed_mask) { HAL_TRACE_ERROR4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...", patchfile_ver_major, patchfile_ver_minor, nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor); #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE)) /* Check if I2C patch is needed: if */ /* - I2C patch file was provided using HAL_NfcPrmSetI2cPatch, and */ /* - current patch in NVM has ProjectID=0, or */ /* FPM is not present or corrupted, or */ /* or patchfile is major-ver 76+ */ /* or patchfile is not for B3 (always download for B4 onward) */ if ( (nfc_hal_cb.prm_i2c.p_patch) &&( (nfc_hal_cb.nvm_cb.project_id == 0) ||(nfc_hal_cb.nvm_cb.fpm_size == 0) ||(nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_FPM_BAD) ||(patchfile_ver_major >= 76) ||(!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3)) )) { HAL_TRACE_DEBUG0 ("I2C patch fix required."); nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED; /* Download i2c fix first */ nfc_hal_prm_spd_download_i2c_fix (); return; } #endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */ /* Download first segment */ nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER; if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)) { /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch segment */ (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH); } else { nfc_hal_prm_spd_handle_next_patch_start (); } } else { static BOOLEAN firstTime = TRUE; if (firstTime) { HAL_TRACE_ERROR2 ("NVM patch version is %d.%d", nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor); firstTime = FALSE; } /* Download complete */ nfc_hal_prm_spd_handle_download_complete (return_code); } }
/******************************************************************************* ** ** Function nfc_hal_prm_spd_download_i2c_fix ** ** Description Start downloading patch for i2c fix ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_spd_download_i2c_fix (void) { UINT8 *p, *p_start; UINT16 patchfile_project_id; UINT16 patchfile_ver_major; UINT16 patchfile_ver_minor; UINT16 patchfile_patchsize; UINT8 u8; HAL_TRACE_DEBUG0 ("Downloading I2C fix..."); /* Save pointer and offset of patchfile, so we can resume after downloading the i2c fix */ nfc_hal_cb.prm.spd_patch_offset = nfc_hal_cb.prm.cur_patch_offset; nfc_hal_cb.prm.spd_patch_len_remaining = nfc_hal_cb.prm.cur_patch_len_remaining; /* Initialize pointers for downloading i2c fix */ nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm_i2c.p_patch; nfc_hal_cb.prm.cur_patch_offset = 0; nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm_i2c.len; /* Parse the i2c patchfile */ if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN) { /* Parse patchfile header */ p = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data; p_start = p; STREAM_TO_UINT16 (patchfile_project_id, p); STREAM_TO_UINT16 (patchfile_ver_major, p); STREAM_TO_UINT16 (patchfile_ver_minor, p); /* RFU */ p++; /* Check how many patches are in the patch file */ STREAM_TO_UINT8 (u8, p); /* Should only be one patch */ if (u8 > 1) { HAL_TRACE_ERROR1 ("Invalid i2c fix: invalid number of patches (%i)", u8); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT); return; } /* Get info about the i2c patch*/ STREAM_TO_UINT8 (u8, p); /* power mode (not needed for i2c patch) */ STREAM_TO_UINT16 (patchfile_patchsize, p); /* size of patch */ /* 5 byte RFU */ p += 5; /* Adjust length to exclude patchfiloe header */ nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start); /* Adjust size of patchfile */ nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start); /* Bytes of patchfile transmitted/processed so far */ /* Begin sending patch to the NFCC */ nfc_hal_prm_spd_send_next_segment (); } else { /* ERROR: Bad length for patchfile */ HAL_TRACE_ERROR0 ("Invalid i2c fix: unexpected end of patch"); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT); } }
/******************************************************************************* ** ** Function nfc_hal_main_task ** ** Description NFC HAL NCI transport event processing task ** ** Returns 0 ** *******************************************************************************/ UINT32 nfc_hal_main_task (UINT32 param) { UINT16 event; UINT8 byte; UINT8 num_interfaces; UINT8 *p; NFC_HDR *p_msg; BOOLEAN free_msg; HAL_TRACE_DEBUG0 ("NFC_HAL_TASK started"); /* Main loop */ while (TRUE) { event = GKI_wait (0xFFFF, 0); /* Handle NFC_HAL_TASK_EVT_INITIALIZE (for initializing NCI transport) */ if (event & NFC_HAL_TASK_EVT_INITIALIZE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_INITIALIZE signal. Opening NFC transport..."); nfc_hal_main_open_transport (); } /* Check for terminate event */ if (event & NFC_HAL_TASK_EVT_TERMINATE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE"); nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); if (nfc_hal_cb.p_stack_cback) { nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK); nfc_hal_cb.p_stack_cback = NULL; } continue; } /* Check for power cycle event */ if (event & NFC_HAL_TASK_EVT_POWER_CYCLE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_POWER_CYCLE"); nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); /* power cycle timeout */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_POWER_CYCLE, (NFC_HAL_POWER_CYCLE_DELAY*QUICK_TIMER_TICKS_PER_SEC)/1000); continue; } /* NCI message ready to be sent to NFCC */ if (event & NFC_HAL_TASK_EVT_MBOX) { while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL) { free_msg = TRUE; switch (p_msg->event & NFC_EVT_MASK) { case NFC_HAL_EVT_TO_NFC_NCI: nfc_hal_main_send_message (p_msg); /* do not free buffer. NCI VS code may keep it for processing later */ free_msg = FALSE; break; case NFC_HAL_EVT_POST_CORE_RESET: NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_POST_INIT_DONE); /* set NCI Control packet size from CORE_INIT_RSP */ p = (UINT8 *) (p_msg + 1) + p_msg->offset + NCI_MSG_HDR_SIZE; p += 5; STREAM_TO_UINT8 (num_interfaces, p); p += (num_interfaces + 3); nfc_hal_cb.ncit_cb.nci_ctrl_size = *p; /* start post initialization */ nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_LPTD; nfc_hal_cb.dev_cb.next_startup_vsc = 1; nfc_hal_dm_config_nfcc (); break; case NFC_HAL_EVT_TO_START_QUICK_TIMER: GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); break; case NFC_HAL_EVT_HCI: nfc_hal_hci_evt_hdlr ((tNFC_HAL_HCI_EVENT_DATA *) p_msg); break; case NFC_HAL_EVT_PRE_DISCOVER: NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE); nfa_hal_send_pre_discover_cfg (); break; case NFC_HAL_EVT_CONTROL_GRANTED: nfc_hal_dm_send_pend_cmd (); break; default: break; } if (free_msg) GKI_freebuf (p_msg); } } /* Data waiting to be read from serial port */ if (event & NFC_HAL_TASK_EVT_DATA_RDY) { while (TRUE) { /* Read one byte to see if there is anything waiting to be read */ if (USERIAL_Read (USERIAL_NFC_PORT, &byte, 1) == 0) { break; } if (nfc_hal_nci_receive_msg (byte)) { /* complete of receiving NCI message */ nfc_hal_nci_assemble_nci_msg (); if (nfc_hal_cb.ncit_cb.p_rcv_msg) { if (nfc_hal_nci_preproc_rx_nci_msg (nfc_hal_cb.ncit_cb.p_rcv_msg)) { /* Send NCI message to the stack */ nfc_hal_send_nci_msg_to_nfc_task (nfc_hal_cb.ncit_cb.p_rcv_msg); } else { if (nfc_hal_cb.ncit_cb.p_rcv_msg) GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg); } nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; } } } /* while (TRUE) */ } /* Process quick timer tick */ if (event & NFC_HAL_QUICK_TIMER_EVT_MASK) { nfc_hal_main_process_quick_timer_evt (); } } HAL_TRACE_DEBUG0 ("nfc_hal_main_task terminated"); GKI_exit_task (GKI_get_taskid ()); return 0; }
/******************************************************************************* ** ** 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); } } }
/******************************************************************************* ** ** Function nci_brcm_lp_timeout_cback ** ** Description callback function for low power timeout ** ** Returns void ** *******************************************************************************/ static void nci_brcm_lp_timeout_cback (void *p_tle) { HAL_TRACE_DEBUG0 ("nci_brcm_lp_timeout_cback ()"); nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TIMEOUT_EVT); }