blob: 3d9e76fdc85000e4b600b95f0a288a2af705eb7e [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2012-2014 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "nfc_hal_int.h"
#include "userial.h"
/*****************************************************************************
* Definitions
*****************************************************************************/
/* Internal flags */
/* Application provided patchram in a single buffer */
#define NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF 0x01
/* Reserved for future use */
#define NFC_HAL_PRM_FLAGS_RFU 0x02
#define NFC_HAL_PRM_FLAGS_SIGNATURE_SENT 0x04 /* Signature sent to NFCC */
#define NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED 0x08 /* PreI2C patch required */
/* B3 Patch (no RESET_NTF after patch download) */
#define NFC_HAL_PRM_FLAGS_BCM20791B3 0x10
#define NFC_HAL_PRM_FLAGS_RM_RF 0x20 /* Erase Personality data */
/* Secure patch download definitions */
/* PRJID + MAJORVER + MINORVER + COUNT */
#define NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN 7
/* Enumeration of power modes IDs */
#define NFC_HAL_PRM_SPD_POWER_MODE_LPM 0
#define NFC_HAL_PRM_SPD_POWER_MODE_FPM 1
/* Version string for BCM20791B3 */
const uint8_t NFC_HAL_PRM_BCM20791B3_STR[] = "20791B3";
#define NFC_HAL_PRM_BCM20791B3_STR_LEN (sizeof(NFC_HAL_PRM_BCM20791B3_STR) - 1)
/* timeout for SPD events (in ms) */
#define NFC_HAL_PRM_SPD_TOUT (6000)
/* delay before sending any new command (ms)*/
#define NFC_HAL_PRM_END_DELAY (250)
#if (NFC_HAL_PRM_DEBUG == TRUE)
#define NFC_HAL_PRM_STATE(str) \
HAL_TRACE_DEBUG2("%s st: %d", str, nfc_hal_cb.prm.state)
#else
#define NFC_HAL_PRM_STATE(str)
#endif
void nfc_hal_prm_post_baud_update(tHAL_NFC_STATUS status);
typedef struct {
uint16_t offset;
uint8_t len;
} tNFC_HAL_PRM_RM_RF;
const tNFC_HAL_PRM_RM_RF nfc_hal_prm_rm_rf_20795a1[] = {
{0x0000, 0xFB}, {0x019C, 0x08}, {0x05E8, 0xFB}, {0, 0}};
static bool nfc_hal_prm_nvm_rw_cmd(void);
/*****************************************************************************
** Extern variable from nfc_hal_dm_cfg.c
*****************************************************************************/
extern tNFC_HAL_CFG* p_nfc_hal_cfg;
/*******************************************************************************
**
** Function nfc_hal_prm_spd_handle_download_complete
**
** Description Patch download complete (for secure patch download)
**
** Returns void
**
*******************************************************************************/
void nfc_hal_prm_spd_handle_download_complete(uint8_t event) {
nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_IDLE;
/* Notify application now */
if (nfc_hal_cb.prm.p_cback) (nfc_hal_cb.prm.p_cback)(event);
}
/*******************************************************************************
**
** 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_t* p_src;
uint16_t len, offset = nfc_hal_cb.prm.cur_patch_offset;
uint8_t hcit, oid, hdr0, type;
uint8_t chipverlen;
uint8_t chipverstr[NCI_SPD_HEADER_CHIPVER_LEN];
uint8_t 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_t*)(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_t*)(nfc_hal_cb.prm.p_cur_patch_data + offset + 1),
(uint8_t)(len + NCI_MSG_HDR_SIZE),
nfc_hal_prm_nci_command_complete_cback);
}
/*******************************************************************************
**
** 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_t cur_patch_mask;
uint32_t cur_patch_len;
bool 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_t)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_t)cur_patch_len;
nfc_hal_cb.prm.cur_patch_offset += (uint16_t)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();
}
#if (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE)
/*******************************************************************************
**
** 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_t *p, *p_start;
uint16_t patchfile_project_id;
uint16_t patchfile_ver_major;
uint16_t patchfile_ver_minor;
uint16_t patchfile_patchsize;
uint8_t 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_t*)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_t)(p - p_start); /* Adjust size of patchfile */
nfc_hal_cb.prm.cur_patch_offset += (uint16_t)(
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);
}
}
#endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
/*******************************************************************************
**
** Function nfc_hal_prm_spd_check_version_continue
**
** Description Check patchfile version with current downloaded version
**
** Returns void
**
*******************************************************************************/
static void nfc_hal_prm_spd_check_version_continue(void) {
HAL_TRACE_DEBUG1("nfc_hal_prm_spd_check_version_continue 0x%02x",
nfc_hal_cb.prm.flags);
if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_RM_RF) {
HAL_TRACE_DEBUG0("erase relevant blocks in NVM");
nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_RM_RF;
if (!nfc_hal_prm_nvm_rw_cmd()) {
/* nvm rw started successfully */
return;
}
}
#if (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE)
if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED) {
HAL_TRACE_DEBUG0("I2C patch 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();
}
}
/*******************************************************************************
**
** 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_t *p, *p_start, i;
uint32_t nvm_patch_present_mask = 0;
uint32_t patchfile_patch_present_mask;
uint16_t patchfile_project_id = 0;
uint16_t patchfile_ver_major = 0;
uint16_t patchfile_ver_minor = 0;
uint16_t patchfile_patchsize;
uint8_t 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_t*)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_t)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_t)(
p - p_start); /* Bytes of patchfile transmitted/processed so far */
nfc_hal_cb.prm.cur_patch_len_remaining -=
(uint16_t)(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;
if (nfc_hal_cb.dev_cb.brcm_hw_id == BRCM_20795A1_ID) {
nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_RM_RF;
nfc_hal_cb.prm.p_param = (void*)nfc_hal_prm_rm_rf_20795a1;
nfc_hal_cb.prm.param_idx = 0;
}
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 (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;
}
#endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
nfc_hal_prm_spd_check_version_continue();
} else {
static bool 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);
}
}
#if (NFC_HAL_TRACE_VERBOSE == TRUE)
/*******************************************************************************
**
** Function nfc_hal_prm_spd_status_str
**
** Description Return status string for a given spd status code
**
** Returns Status string
**
*******************************************************************************/
uint8_t* nfc_hal_prm_spd_status_str(uint8_t spd_status_code) {
char* p_str;
switch (spd_status_code) {
case NCI_STATUS_SPD_ERROR_DEST:
p_str = "SPD_ERROR_DEST";
break;
case NCI_STATUS_SPD_ERROR_PROJECTID:
p_str = "SPD_ERROR_PROJECTID";
break;
case NCI_STATUS_SPD_ERROR_CHIPVER:
p_str = "SPD_ERROR_CHIPVER";
break;
case NCI_STATUS_SPD_ERROR_MAJORVER:
p_str = "SPD_ERROR_MAJORVER";
break;
case NCI_STATUS_SPD_ERROR_INVALID_PARAM:
p_str = "SPD_ERROR_INVALID_PARAM";
break;
case NCI_STATUS_SPD_ERROR_INVALID_SIG:
p_str = "SPD_ERROR_INVALID_SIG";
break;
case NCI_STATUS_SPD_ERROR_NVM_CORRUPTED:
p_str = "SPD_ERROR_NVM_CORRUPTED";
break;
case NCI_STATUS_SPD_ERROR_PWR_MODE:
p_str = "SPD_ERROR_PWR_MODE";
break;
case NCI_STATUS_SPD_ERROR_MSG_LEN:
p_str = "SPD_ERROR_MSG_LEN";
break;
case NCI_STATUS_SPD_ERROR_PATCHSIZE:
p_str = "SPD_ERROR_PATCHSIZE";
break;
default:
p_str = "Unspecified Error";
break;
}
return ((uint8_t*)p_str);
}
#endif /* (NFC_HAL_TRACE_VERBOSE == TRUE) */
/*******************************************************************************
**
** Function nfc_hal_prm_nvm_rw_cmd
**
** Description Non Volatile Read Write Command; for now only write zeros
**
** Returns TRUE if done.
**
*******************************************************************************/
static bool nfc_hal_prm_nvm_rw_cmd(void) {
tNFC_HAL_PRM_RM_RF* p_param = (tNFC_HAL_PRM_RM_RF*)(nfc_hal_cb.prm.p_param);
uint8_t *p_buff, *p, *p_end;
uint8_t len = 0;
uint16_t cmd_len;
if (p_param) len = p_param[nfc_hal_cb.prm.param_idx].len;
HAL_TRACE_DEBUG2("nfc_hal_prm_nvm_rw_cmd: %d/%d", nfc_hal_cb.prm.param_idx,
len);
if (len == 0) {
return true;
}
cmd_len = len + 7;
p_buff = (uint8_t*)GKI_getbuf(cmd_len);
if (p_buff == NULL) {
HAL_TRACE_ERROR0("NVM No buffer");
nfc_hal_prm_spd_handle_download_complete(NFC_HAL_PRM_ABORT_EVT);
return true;
}
p = p_buff;
UINT8_TO_STREAM(p, (NCI_MTS_CMD | NCI_GID_PROP));
UINT8_TO_STREAM(p, NCI_MSG_EEPROM_RW);
UINT8_TO_STREAM(p, (len + 4));
UINT8_TO_STREAM(p, 1); /* 1=write 0=read */
UINT16_TO_STREAM(p, p_param[nfc_hal_cb.prm.param_idx].offset);
UINT8_TO_STREAM(p, len);
memset(p, 0, len); /* Fill remaining bytes with zeros*/
nfc_hal_cb.prm.param_idx++;
nfc_hal_dm_send_nci_cmd(p_buff, cmd_len,
nfc_hal_prm_nci_command_complete_cback);
GKI_freebuf(p_buff);
return false;
}
/*******************************************************************************
**
** 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_t data_len,
uint8_t* p_data) {
uint8_t status, u8;
uint8_t* p;
uint32_t 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) */
nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTHENTICATING;
nfc_hal_main_start_quick_timer(
&nfc_hal_cb.prm.timer, 0x00,
(NFC_HAL_PRM_COMMIT_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 (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 if (event == NFC_VS_EEPROM_RW_EVT) {
STREAM_TO_UINT8(status, p);
if (status == NCI_STATUS_OK) {
if (nfc_hal_prm_nvm_rw_cmd()) {
nfc_hal_prm_spd_check_version_continue();
}
} else {
HAL_TRACE_ERROR0("NVM failed");
nfc_hal_prm_spd_handle_download_complete(NFC_HAL_PRM_ABORT_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_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_t 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_t)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_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_t reset_reason, uint8_t 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_post_final_baud_update
**
** Description: Called after baud rate udate
**
** Returns: Nothing
**
*******************************************************************************/
void nfc_hal_prm_post_baud_update(tHAL_NFC_STATUS status) {
NFC_HAL_PRM_STATE("nfc_hal_prm_post_baud_update");
if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE) {
/* Proceed with next step of patch download sequence */
nfc_hal_prm_nfcc_ready_to_continue();
}
}
/*******************************************************************************
**
** 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 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
**
**
*******************************************************************************/
bool HAL_NfcPrmDownloadStart(tNFC_HAL_PRM_FORMAT format_type,
uint32_t dest_address, uint8_t* p_patchram_buf,
uint32_t patchram_len, uint32_t 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_t)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_t)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 HAL_NfcPrmDownloadContinue
**
** Description Send next segment of patchram to controller. Called when
** NFC_HAL_PRM_CONTINUE_EVT is received.
**
** Only needed if HAL_NfcPrmDownloadStart was called with
** p_patchram_buf=NULL
**
** Input Params p_patch_data pointer to patch data
** patch_data_len patch data len
**
** Returns TRUE if successful, otherwise FALSE
**
*******************************************************************************/
bool HAL_NfcPrmDownloadContinue(uint8_t* p_patch_data,
uint16_t patch_data_len) {
HAL_TRACE_API2("HAL_NfcPrmDownloadContinue ():state = %d, patch_data_len=%d",
nfc_hal_cb.prm.state, patch_data_len);
/* Check if we are in a valid state for this API */
if ((nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_COMPARE_VERSION) &&
(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER) &&
(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_DOWNLOADING))
return false;
if (patch_data_len == 0) return false;
nfc_hal_cb.prm.cur_patch_offset = 0;
nfc_hal_cb.prm.p_cur_patch_data = p_patch_data;
nfc_hal_cb.prm.cur_patch_len_remaining = patch_data_len;
/* Call appropriate handler */
if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_COMPARE_VERSION) {
nfc_hal_prm_spd_check_version();
} else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER) {
nfc_hal_prm_spd_handle_next_patch_start();
} else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_DOWNLOADING) {
nfc_hal_prm_spd_send_next_segment();
} else {
HAL_TRACE_ERROR1("Unexpected patch state:%d.", nfc_hal_cb.prm.state);
}
return true;
}
/*******************************************************************************
**
** Function HAL_NfcPrmSetI2cPatch
**
** Description Specify patchfile for BCM20791B3 I2C fix. This fix
** must be downloaded prior to initial patch download for I2C
** transport
**
** Input Params p_i2c_patchfile_buf: pointer to patch for i2c fix
** i2c_patchfile_len: length of patch
** prei2c_delay: the delay before downloading main patch
** if 0 is given, NFC_HAL_PRM_POST_I2C_FIX_DELAY
*is used instead.
**
** Returns Nothing
**
**
*******************************************************************************/
void HAL_NfcPrmSetI2cPatch(uint8_t* p_i2c_patchfile_buf,
uint16_t i2c_patchfile_len, uint32_t prei2c_delay) {
#if (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE)
HAL_TRACE_API0("HAL_NfcPrmSetI2cPatch ()");
nfc_hal_cb.prm_i2c.prei2c_delay = NFC_HAL_PRM_POST_I2C_FIX_DELAY;
if (prei2c_delay) nfc_hal_cb.prm_i2c.prei2c_delay = prei2c_delay;
nfc_hal_cb.prm_i2c.p_patch = p_i2c_patchfile_buf;
nfc_hal_cb.prm_i2c.len = i2c_patchfile_len;
#endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
}
/*******************************************************************************
**
** Function HAL_NfcPrmSetSpdNciCmdPayloadSize
**
** Description Set Host-to-NFCC NCI message size for secure patch download
**
** This API must be called before calling
*HAL_NfcPrmDownloadStart.
** If the API is not called, then PRM will use the default
** message size.
**
** Typically, this API is only called for platforms that have
** message-size limitations in the transport/driver.
**
** Valid message size range:
*NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE to 255.
**
** Returns HAL_NFC_STATUS_OK if successful
** HAL_NFC_STATUS_FAILED otherwise
**
**
*******************************************************************************/
tHAL_NFC_STATUS HAL_NfcPrmSetSpdNciCmdPayloadSize(uint8_t max_payload_size) {
/* Validate: minimum size is NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE */
if (max_payload_size < NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE) {
HAL_TRACE_ERROR2(
"HAL_NfcPrmSetSpdNciCmdPayloadSize: invalid size (%i). Must be between "
"%i and 255",
max_payload_size, NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE);
return (HAL_NFC_STATUS_FAILED);
} else {
HAL_TRACE_API1(
"HAL_NfcPrmSetSpdNciCmdPayloadSize: new message size during download: "
"%i",
max_payload_size);
nfc_hal_cb.ncit_cb.nci_ctrl_size = max_payload_size;
return (HAL_NFC_STATUS_OK);
}
}