/*******************************************************************************
**
** Function         nfc_hal_dm_send_get_build_info_cmd
**
** Description      Send NCI_MSG_GET_BUILD_INFO CMD
**
** Returns          void
**
*******************************************************************************/
void nfc_hal_dm_send_get_build_info_cmd (void)
{
    NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_BUILD_INFO);

    /* get build information to find out HW */
    nfc_hal_dm_send_nci_cmd (nfc_hal_dm_get_build_info_cmd, NCI_MSG_HDR_SIZE, NULL);
}
/*******************************************************************************
**
** 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_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         nfc_hal_dm_set_fw_fsm
**
** Description      Enable or disable FW FSM
**
** Returns          void
**
*******************************************************************************/
void nfc_hal_dm_set_fw_fsm (BOOLEAN enable, tNFC_HAL_NCI_CBACK *p_cback)
{
    if (enable)
        nfc_hal_dm_set_fw_fsm_cmd[NCI_SET_FWFSM_OFFSET_ENABLE] = 0x01; /* Enable, default is disabled */
    else
        nfc_hal_dm_set_fw_fsm_cmd[NCI_SET_FWFSM_OFFSET_ENABLE] = 0x00; /* Disable */

    nfc_hal_dm_send_nci_cmd (nfc_hal_dm_set_fw_fsm_cmd, NCI_MSG_HDR_SIZE + 1, p_cback);
}
/*******************************************************************************
**
** Function         nfc_hal_dm_check_xtal
**
** Description      check if need to send xtal command.
**                  If not, proceed to next step get_patch_version.
**
** Returns          void
**
*******************************************************************************/
static void nfc_hal_dm_check_xtal (void)
{
    UINT16  xtal_freq;
    tNFC_HAL_XTAL_INDEX xtal_index;

    /* if NFCC needs to set Xtal frequency before getting patch version */
    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_MAX) || (xtal_index == NFC_HAL_XTAL_INDEX_SPECIAL))
    {
        {
            /* set Xtal index before getting patch version */
            nfc_hal_dm_set_xtal_freq_index ();
            return;
        }
    }

    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_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_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_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_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;
}
/*******************************************************************************
**
** 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];
    UINT16  xtal_freq;

    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 (nfc_hal_cb.dev_cb.brcm_hw_id, p);

            STREAM_TO_UINT8 (chipverlen, p);
            memset (chipverstr, 0, NCI_SPD_HEADER_CHIPVER_LEN);

            STREAM_TO_ARRAY (chipverstr, p, chipverlen);

            if ((chipverlen == NFC_HAL_DM_BCM20791B3_STR_LEN) && (memcmp (NFC_HAL_DM_BCM20791B3_STR, chipverstr, NFC_HAL_DM_BCM20791B3_STR_LEN) == 0))
            {
                /* BCM2079B3 FW - eSE restarted for patch download */
                nfc_hal_cb.hci_cb.hci_fw_workaround         = TRUE;
                nfc_hal_cb.hci_cb.hci_fw_validate_netwk_cmd = TRUE;
            }
            else if (  ((chipverlen == NFC_HAL_DM_BCM20791B4_STR_LEN) && (memcmp (NFC_HAL_DM_BCM20791B4_STR, chipverstr, NFC_HAL_DM_BCM20791B4_STR_LEN) == 0))
                     ||((chipverlen == NFC_HAL_DM_BCM43341B0_STR_LEN) && (memcmp (NFC_HAL_DM_BCM43341B0_STR, chipverstr, NFC_HAL_DM_BCM43341B0_STR_LEN) == 0))  )
            {
                /* BCM43341B0/BCM2079B4 FW - eSE restarted for patch download */
                nfc_hal_cb.hci_cb.hci_fw_workaround         = TRUE;
                nfc_hal_cb.hci_cb.hci_fw_validate_netwk_cmd = FALSE;
            }
            else
            {
                /* BCM2079B5 FW - eSE not be restarted for patch download from UICC */
                nfc_hal_cb.hci_cb.hci_fw_workaround         = FALSE;
                nfc_hal_cb.hci_cb.hci_fw_validate_netwk_cmd = FALSE;
            }

            /* if NFCC needs to set Xtal frequency before getting patch version */
            if (nfc_hal_dm_get_xtal_index (nfc_hal_cb.dev_cb.brcm_hw_id, &xtal_freq) < NFC_HAL_XTAL_INDEX_MAX)
            {
                {
                    /* set Xtal index before getting patch version */
                    nfc_hal_dm_set_xtal_freq_index ();
                    return;
                }
            }

            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);
        }
        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);
        }
    }
}