/******************************************************************************* ** ** 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_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_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_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_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_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_send_credit_ntf_for_cid ** ** Description This function is called to send credit ntf ** for the specified connection id to nfc task ** ** Returns void ** *******************************************************************************/ static void nfc_hal_send_credit_ntf_for_cid (UINT8 cid) { NFC_HDR *p_msg; UINT8 *p, *ps; /* Start of new message. Allocate a buffer for message */ if ((p_msg = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL) { /* Initialize NFC_HDR */ p_msg->len = NCI_DATA_HDR_SIZE + 0x03; p_msg->event = 0; p_msg->offset = 0; p_msg->layer_specific = 0; p = (UINT8 *) (p_msg + 1) + p_msg->offset; ps = p; NCI_MSG_BLD_HDR0(p, NCI_MT_NTF, NCI_GID_CORE); NCI_MSG_BLD_HDR1(p, NCI_MSG_CORE_CONN_CREDITS); UINT8_TO_STREAM (p, 0x03); /* Number of credit entries */ *p++ = 0x01; /* Connection id of the credit ntf */ *p++ = cid; /* Number of credits */ *p = 0x01; #ifdef DISP_NCI DISP_NCI (ps, (UINT16) p_msg->len, TRUE); #endif nfc_hal_send_nci_msg_to_nfc_task (p_msg); } else { HAL_TRACE_ERROR0 ("Unable to allocate buffer for Sending credit ntf to stack"); } }
/******************************************************************************* ** ** Function HAL_NfcPrmDownloadStart ** ** Description Initiate patch download ** ** Input Params ** format_type patch format type ** (NFC_HAL_PRM_FORMAT_BIN, NFC_HAL_PRM_FORMAT_HCD, or ** NFC_HAL_PRM_FORMAT_NCD) ** ** dest_address destination adderess (needed for BIN format only) ** ** p_patchram_buf pointer to patchram buffer. If NULL, ** then app must call HAL_NfcPrmDownloadContinue when ** NFC_HAL_PRM_CONTINUE_EVT is received, to send the next ** segment of patchram ** ** patchram_len size of p_patchram_buf (if non-NULL) ** ** patchram_delay The delay after each patch. ** If the given value is less than the size of the patchram, ** the size of patchram is used instead. ** ** p_cback callback for download status ** ** ** Returns TRUE if successful, otherwise FALSE ** ** *******************************************************************************/ BOOLEAN HAL_NfcPrmDownloadStart (tNFC_HAL_PRM_FORMAT format_type, UINT32 dest_address, UINT8 *p_patchram_buf, UINT32 patchram_len, UINT32 patchram_delay, tNFC_HAL_PRM_CBACK *p_cback) { HAL_TRACE_API0 ("HAL_NfcPrmDownloadStart ()"); memset (&nfc_hal_cb.prm, 0, sizeof (tNFC_HAL_PRM_CB)); if (p_patchram_buf) { nfc_hal_cb.prm.p_cur_patch_data = p_patchram_buf; nfc_hal_cb.prm.cur_patch_offset = 0; nfc_hal_cb.prm.cur_patch_len_remaining = (UINT16) patchram_len; nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF; if (patchram_len == 0) return FALSE; } nfc_hal_cb.prm.p_cback = p_cback; nfc_hal_cb.prm.dest_ram = dest_address; nfc_hal_cb.prm.format = format_type; nfc_hal_cb.prm.patchram_delay = patchram_delay; nfc_hal_cb.prm.timer.p_cback = nfc_hal_prm_process_timeout; if (format_type == NFC_HAL_PRM_FORMAT_NCD) { /* Store patch buffer pointer and length */ nfc_hal_cb.prm.p_spd_patch = p_patchram_buf; nfc_hal_cb.prm.spd_patch_len_remaining = (UINT16)patchram_len; nfc_hal_cb.prm.spd_patch_offset = 0; /* If patch download is required, but no NVM is available, then abort */ if ((p_nfc_hal_cfg->nfc_hal_prm_nvm_required) && (nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_NO_NVM)) { HAL_TRACE_ERROR0 ("This platform requires NVM and the NVM is not available - Abort"); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_NO_NVM_EVT); return FALSE; } /* Compare patch version in NVM with version in patchfile */ nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_COMPARE_VERSION; if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF) { /* If patchfile is in a buffer, get patch version from buffer */ nfc_hal_prm_spd_check_version (); } else { /* If patchfile is not in a buffer, then request patchfile header from adaptation layer. */ (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_PATCHFILE_HDR_EVT); } } else { HAL_TRACE_ERROR0 ("Unexpected patch format."); return FALSE; } return TRUE; }
/******************************************************************************* ** ** Function nfc_hal_prm_spd_send_next_segment ** ** Description Send next patch segment (for secure patch download) ** ** Returns void ** *******************************************************************************/ void nfc_hal_prm_spd_send_next_segment (void) { UINT8 *p_src; UINT16 len, offset = nfc_hal_cb.prm.cur_patch_offset; UINT8 hcit, oid, hdr0, type; UINT8 chipverlen; UINT8 chipverstr[NCI_SPD_HEADER_CHIPVER_LEN]; UINT8 patch_hdr_size = NCI_MSG_HDR_SIZE + 1; /* 1 is for HCIT */ /* Validate that segment is at least big enought to have NCI_MSG_HDR_SIZE + 1 (hcit) */ if (nfc_hal_cb.prm.cur_patch_len_remaining < patch_hdr_size) { HAL_TRACE_ERROR0 ("Unexpected end of patch."); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT); return; } /* Parse NCI command header */ p_src = (UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset); STREAM_TO_UINT8 (hcit, p_src); STREAM_TO_UINT8 (hdr0, p_src); STREAM_TO_UINT8 (oid, p_src); STREAM_TO_UINT8 (len, p_src); STREAM_TO_UINT8 (type, p_src); /* Update number of bytes comsumed */ nfc_hal_cb.prm.cur_patch_offset += (len + patch_hdr_size); nfc_hal_cb.prm.cur_patch_len_remaining -= (len + patch_hdr_size); /* Check if sending signature byte */ if ( (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD ) &&(type == NCI_SPD_TYPE_SIGNATURE) ) { nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_SIGNATURE_SENT; } /* Check for header */ else if ( (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD ) &&(type == NCI_SPD_TYPE_HEADER) ) { /* Check if patch is for BCM20791B3 */ p_src += NCI_SPD_HEADER_OFFSET_CHIPVERLEN; STREAM_TO_UINT8 (chipverlen, p_src); if (memcmp (nfc_hal_cb.nvm_cb.chip_ver, p_src, chipverlen) != 0) { HAL_TRACE_ERROR0 ("Unexpected chip ver."); nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT); return; } STREAM_TO_ARRAY (chipverstr, p_src, NCI_SPD_HEADER_CHIPVER_LEN); if (memcmp (NFC_HAL_PRM_BCM20791B3_STR, chipverstr, NFC_HAL_PRM_BCM20791B3_STR_LEN) == 0) { /* Patch is for BCM2079B3 - do not wait for RESET_NTF after patch download */ nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_BCM20791B3; } else { /* Patch is for BCM2079B4 or newer - wait for RESET_NTF after patch download */ nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_BCM20791B3; } } /* Send the command (not including HCIT here) */ nfc_hal_dm_send_nci_cmd ((UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset + 1), (UINT8) (len + NCI_MSG_HDR_SIZE), nfc_hal_prm_nci_command_complete_cback); }
/******************************************************************************* ** ** 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_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_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_set_config ** ** Description Send NCI config items to NFCC ** ** Returns tHAL_NFC_STATUS ** *******************************************************************************/ tHAL_NFC_STATUS nfc_hal_dm_set_config (UINT8 tlv_size, UINT8 *p_param_tlvs, tNFC_HAL_NCI_CBACK *p_cback) { UINT8 *p_buff, *p; UINT8 num_param = 0, param_len, rem_len, *p_tlv; UINT16 cmd_len = NCI_MSG_HDR_SIZE + tlv_size + 1; tHAL_NFC_STATUS status = HAL_NFC_STATUS_FAILED; if ((tlv_size == 0)||(p_param_tlvs == NULL)) { return status; } if ((p_buff = (UINT8 *) GKI_getbuf ((UINT16)(NCI_MSG_HDR_SIZE + tlv_size))) != NULL) { p = p_buff; NCI_MSG_BLD_HDR0 (p, NCI_MT_CMD, NCI_GID_CORE); NCI_MSG_BLD_HDR1 (p, NCI_MSG_CORE_SET_CONFIG); UINT8_TO_STREAM (p, (UINT8) (tlv_size + 1)); rem_len = tlv_size; p_tlv = p_param_tlvs; while (rem_len > 1) { num_param++; /* number of params */ p_tlv ++; /* param type */ param_len = *p_tlv++; /* param length */ rem_len -= 2; /* param type and length */ if (rem_len >= param_len) { rem_len -= param_len; p_tlv += param_len; /* next param_type */ if (rem_len == 0) { status = HAL_NFC_STATUS_OK; break; } } else { /* error found */ break; } } if (status == HAL_NFC_STATUS_OK) { UINT8_TO_STREAM (p, num_param); ARRAY_TO_STREAM (p, p_param_tlvs, tlv_size); nfc_hal_dm_send_nci_cmd (p_buff, cmd_len, p_cback); } else { HAL_TRACE_ERROR0 ("nfc_hal_dm_set_config ():Bad TLV"); } GKI_freebuf (p_buff); } return status; }