/*
* Copyright (C) 2010 NXP Semiconductors
*
* 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.
*/
/*
* \file phFriNfc_MifStdFormat.c
* \brief NFC Ndef Formatting For Mifare standard card.
*
* Project: NFC-FRI
*
* $Date: Tue Oct 20 20:13:03 2009 $
* $Author: ing02260 $
* $Revision: 1.9 $
* $Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
*
*/
#include <phFriNfc_MifStdFormat.h>
#include <phFriNfc_OvrHal.h>
/*! \ingroup grp_file_attributes
* \name NDEF Mapping
*
* File: \ref phFriNfc_MifStdFormat.c
*
*/
/*@{*/
#define PHFRINFCMIFSTDFMT_FILEREVISION "$Revision: 1.9 $"
#define PHFRINFCMIFSTDFMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $"
/*@}*/
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function fills the
* send buffer for transceive function
*/
static void phFriNfc_MfStd_H_FillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
uint16_t BlockNo);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function authenticates
* a block or a sector from the card.
*/
static NFCSTATUS phFriNfc_MfStd_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function calls
* disconnect.
*/
static NFCSTATUS phFriNfc_MfStd_H_CallDisCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
NFCSTATUS Status);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function calls
* disconnect.
*/
static NFCSTATUS phFriNfc_MfStd_H_CallCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
#ifndef PH_HAL4_ENABLE
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function calls
* disconnect.
*/
static NFCSTATUS phFriNfc_MfStd_H_CallPoll(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
#endif /* #ifndef PH_HAL4_ENABLE */
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the
* poll call.
*/
static NFCSTATUS phFriNfc_MfStd_H_ProCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the
* authenticate call.
*/
static NFCSTATUS phFriNfc_MfStd_H_ProAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the
* read access bit call.
*/
static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the
* write access bit call.
*/
static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function writes the
* sector trailer using the block number.
*/
static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function checks the
* access bits of each sector trailer.
*/
static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo,
const uint8_t *RecvBuf,
const uint8_t AcsBits1[],
const uint8_t AcsBits2[]);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function change the
* authentication state and change the block number if required
*/
static void phFriNfc_MfStd_H_ChangeAuthSt(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function finds the
* contiguous ndef compliant blocks.
*/
static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes,
uint8_t Sector[]);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function writes the
* MAD block values.
*/
static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process
* the error status of the authentication
*/
static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process
* the error status of the writing sector trailer
*/
static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process
* the error status of the reading sector trailer
*/
static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process
* the error status of the writing sector trailer
*/
static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall store the
* ndef compliant in the MAD array which will be later used for updating the MAD sector
*/
static void phFriNfc_MfStd_H_StrNdefData(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall find the ndef compliant
* and calculate the block number to write the NDEF TLV
*/
static void phFriNfc_MfStd_H_BlkNoToWrTLV(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static int phFriNfc_MfStd_MemCompare ( void *s1, void *s2, unsigned int n );
void phFriNfc_MfStd_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
uint8_t NfcForSectArray[] = PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT,
MADSectArray[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K;
/* Authentication state */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_VAL_1;
/* Set default key for A or B */
(void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.Default_KeyA_OR_B,
PH_FRINFC_MFSTD_FMT_DEFAULT_KEY, /* 0xFF */
PH_FRINFC_MFSTD_FMT_VAL_6);
/* MAD sector key A */
(void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA,
MADSectArray, //PH_FRINFC_MFSTD_FMT_VAL_0,
PH_FRINFC_MFSTD_FMT_VAL_6);
/* Copy access bits for MAD sectors */
(void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_AccessBits,
&MADSectArray[PH_FRINFC_MFSTD_FMT_VAL_6],
PH_FRINFC_MFSTD_FMT_VAL_3);
/* NFC forum sector key A */
(void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA,
NfcForSectArray, //PH_FRINFC_MFSTD_FMT_VAL_0,
PH_FRINFC_MFSTD_FMT_VAL_6);
/* Copy access bits for NFC forum sectors */
(void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_AccessBits,
&NfcForSectArray[PH_FRINFC_MFSTD_FMT_VAL_6],
PH_FRINFC_MFSTD_FMT_VAL_3);
/* Sector compliant array initialised to 0 */
(void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl,
PH_FRINFC_MFSTD_FMT_VAL_0, /* 0x00 */
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K);
NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_0;
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t)PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK;
}
NFCSTATUS phFriNfc_MfStd_Format( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, const uint8_t *ScrtKeyB )
{
NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_PARAMETER);
uint8_t index = PH_FRINFC_MFSTD_FMT_VAL_0;
if(ScrtKeyB != NULL)
{
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk =
PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK;
/* Store Key B in the context */
while(index < PH_FRINFC_MFSTD_FMT_VAL_6)
{
NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB[index] = ScrtKeyB[index];
index++;
}
/* Set the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* Initialise current block to the first sector trailer */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = PH_FRINFC_MFSTD_FMT_VAL_3;
/* Set the authenticate state */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;
/* Start authentication */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
return Result;
}
void phFriNfc_MfStd_Process(void *Context,
NFCSTATUS Status)
{
phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
/* Copy the formatting status */
NdefSmtCrdFmt->FmtProcStatus = Status;
if(Status == NFCSTATUS_SUCCESS)
{
switch(NdefSmtCrdFmt->State)
{
case PH_FRINFC_MFSTD_FMT_AUTH_SECT:
Status = phFriNfc_MfStd_H_ProAuth(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_DIS_CON:
#ifndef PH_HAL4_ENABLE
Status = phFriNfc_MfStd_H_CallPoll(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_POLL:
#endif /* #ifndef PH_HAL4_ENABLE */
Status = phFriNfc_MfStd_H_CallCon(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_CON:
Status = phFriNfc_MfStd_H_ProCon(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_RD_SECT_TR:
Status = phFriNfc_MfStd_H_ProRdSectTr(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_WR_SECT_TR:
Status = phFriNfc_MfStd_H_ProWrSectTr(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_WR_MAD_BLK:
Status = phFriNfc_MfStd_H_ProWrMADBlk(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_WR_TLV:
break;
case PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK:
Status = phFriNfc_MfStd_H_ProUpdMADBlk(NdefSmtCrdFmt);
break;
default:
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
break;
}
}
else
{
switch(NdefSmtCrdFmt->State)
{
case PH_FRINFC_MFSTD_FMT_AUTH_SECT:
Status = phFriNfc_MfStd_H_ProErrAuth(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_WR_SECT_TR:
Status = phFriNfc_MfStd_H_ErrWrSectTr(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_RD_SECT_TR:
Status = phFriNfc_MfStd_H_ErrRdSectTr(NdefSmtCrdFmt);
break;
default:
Status = NdefSmtCrdFmt->FmtProcStatus;
break;
}
}
/* Status is not success then call completion routine */
if(Status != NFCSTATUS_PENDING)
{
phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status);
}
}
static void phFriNfc_MfStd_H_FillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
uint16_t BlockNo)
{
void *mem = NULL;
uint8_t MADSectTr1k[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K, /* MAD key A,
Access bits and GPB of MAD sector */
MADSectTr4k[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_4K, /* MAD key A,
Access bits and GPB of MAD sector */
NFCSectTr[] = PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT, /* NFC forum key A,
Access bits and GPB of NFC sector */
NDEFMsgTLV[16] = {0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, /* NDEF message TLV (INITIALISED state) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00},
MADBlk[16] = {0x0F, 0x00, 0x03, 0xE1, 0x03, 0xE1,
0x03, 0xE1, 0x03, 0xE1,
0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
/* Block number in send buffer */
NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_0] = (uint8_t)BlockNo;
/* Initialise send receive length */
*NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_MFSTD_FMT_MAX_RECV_LENGTH;
/* Depending on the different state, fill the send buffer */
switch(NdefSmtCrdFmt->State)
{
case PH_FRINFC_MFSTD_FMT_AUTH_SECT:
/* Depending on the authentication state, fill the send buffer */
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState)
{
case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY:
case PH_FRINFC_MFSTD_FMT_AUTH_KEYB:
/* Fill send buffer with the default key */
PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem);
break;
case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY:
/* Fill send buffer with NFC forum sector key */
PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem);
break;
case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB:
/* Fill send buffer with NFC forum sector key */
PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem);
break;
case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY:
default:
/* Fill send buffer with MAD sector key */
PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem);
break;
}
break;
case PH_FRINFC_MFSTD_FMT_RD_SECT_TR:
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
#endif /* #ifdef PH_HAL4_ENABLE */
/* Send length is always one for read operation */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_1;
break;
case PH_FRINFC_MFSTD_FMT_WR_SECT_TR:
/* Fill send buffer for writing sector trailer */
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16;
#endif /* #ifdef PH_HAL4_ENABLE */
/* Copy the relevant sector trailer value in the buffer */
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock)
{
case PH_FRINFC_MFSTD_FMT_VAL_3:
if (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)
{
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
MADSectTr1k,
sizeof(MADSectTr1k));
}
else
{
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
MADSectTr4k,
sizeof(MADSectTr4k));
}
break;
case 67:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
MADSectTr4k,
sizeof(MADSectTr4k));
break;
default:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
NFCSectTr,
sizeof(NFCSectTr));
break;
}
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_11],
NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB,
sizeof(NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB));
/* Send length is always 17 for write operation */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH;
break;
case PH_FRINFC_MFSTD_FMT_WR_TLV:
/* Fill send buffer for writing TLV */
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16;
#endif /* #ifdef PH_HAL4_ENABLE */
/* Copy the NDEF message TLV */
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
NDEFMsgTLV, sizeof(NDEFMsgTLV));
/* Send length is always 17 for write operation */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH;
break;
case PH_FRINFC_MFSTD_FMT_WR_MAD_BLK:
/* Fill send buffer for writing MAD block */
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16;
#endif /* #ifdef PH_HAL4_ENABLE */
if((BlockNo == PH_FRINFC_MFSTD_FMT_VAL_2) ||
(BlockNo == 65) || (BlockNo == 66))
{
/* MAD block number 2, 65 and 66 has 0x03, 0xE1 in the
first two bytes */
MADBlk[PH_FRINFC_MFSTD_FMT_VAL_0] = 0x03;
MADBlk[PH_FRINFC_MFSTD_FMT_VAL_1] = 0xE1;
}
/* Copy the MAD Block values */
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
MADBlk, sizeof(MADBlk));
/* Send length is always 17 for write operation */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH;
break;
case PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK:
default:
/* Fill send buffer for writing MAD block */
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16;
#endif /* #ifdef PH_HAL4_ENABLE */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH;
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk)
{
case PH_FRINFC_MFSTD_FMT_MAD_BLK_1:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk,
(PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1));
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_2:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
&NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[16],
(PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1));
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_64:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
&NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[32],
(PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1));
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_65:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
&NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[48],
(PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1));
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_66:
default:
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
&NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[64],
(PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1));
break;
}
break;
}
PHNFC_UNUSED_VARIABLE(mem);
}
static NFCSTATUS phFriNfc_MfStd_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/* set the data for additional data exchange*/
NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
NdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0;
/*set the completion routines for the card operations*/
NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process;
NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt;
*NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;
/* Call the Overlapped HAL Transceive function */
Result = phFriNfc_OvrHal_Transceive( NdefSmtCrdFmt->LowerDevice,
&NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
NdefSmtCrdFmt->psRemoteDevInfo,
NdefSmtCrdFmt->Cmd,
&NdefSmtCrdFmt->psDepAdditionalInfo,
NdefSmtCrdFmt->SendRecvBuf,
NdefSmtCrdFmt->SendLength,
NdefSmtCrdFmt->SendRecvBuf,
NdefSmtCrdFmt->SendRecvLength);
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_CallDisCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
NFCSTATUS Status)
{
NFCSTATUS Result = Status;
/*Set Ndef State*/
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_DIS_CON;
#ifdef PH_HAL4_ENABLE
/*Call the Overlapped HAL POLL function */
Result = phFriNfc_OvrHal_Reconnect( NdefSmtCrdFmt->LowerDevice,
&NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
NdefSmtCrdFmt->psRemoteDevInfo);
#else
/*Call the Overlapped HAL POLL function */
Result = phFriNfc_OvrHal_Disconnect( NdefSmtCrdFmt->LowerDevice,
&NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
NdefSmtCrdFmt->psRemoteDevInfo);
#endif /* #ifdef PH_HAL4_ENABLE */
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_CallCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/*Set Ndef State*/
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_CON;
/*Call the Overlapped HAL POLL function */
#ifdef PH_HAL4_ENABLE
Result = phFriNfc_OvrHal_Connect( NdefSmtCrdFmt->LowerDevice,
&NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
NdefSmtCrdFmt->psRemoteDevInfo,
NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam);
#else
Result = phFriNfc_OvrHal_Connect( NdefSmtCrdFmt->LowerDevice,
&NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
phHal_eOpModesMifare,
NdefSmtCrdFmt->psRemoteDevInfo,
NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam);
#endif /* #ifdef PH_HAL4_ENABLE */
return Result;
}
#ifndef PH_HAL4_ENABLE
static NFCSTATUS phFriNfc_MfStd_H_CallPoll(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/*Set ndef State*/
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_POLL;
/* Opmodes */
NdefSmtCrdFmt->OpModeType[PH_FRINFC_MFSTD_FMT_VAL_0] = phHal_eOpModesMifare;
NdefSmtCrdFmt->OpModeType[PH_FRINFC_MFSTD_FMT_VAL_1] = phHal_eOpModesArrayTerminator;
/* Number of devices to poll */
NdefSmtCrdFmt->AddInfo.MfStdInfo.NoOfDevices = PH_FRINFC_MFSTD_FMT_VAL_1;
/*Call the Overlapped HAL POLL function */
Result = phFriNfc_OvrHal_Poll( NdefSmtCrdFmt->LowerDevice,
&NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
NdefSmtCrdFmt->OpModeType,
NdefSmtCrdFmt->psRemoteDevInfo,
&NdefSmtCrdFmt->AddInfo.MfStdInfo.NoOfDevices,
NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam);
return Result;
}
#endif /* #ifndef PH_HAL4_ENABLE */
static NFCSTATUS phFriNfc_MfStd_H_ProCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL},
index = PH_FRINFC_MFSTD_FMT_VAL_1;
uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1;
phFriNfc_MfStd_H_ChangeAuthSt(NdefSmtCrdFmt);
if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK)
{
PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD();
}
else
{
/* Set the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* Start authentication */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_ProAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/* Depending on the authentication key check the */
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState)
{
case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY:
if((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock ==
PH_FRINFC_MFSTD_FMT_VAL_3) &&
(NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag ==
PH_FRINFC_MFSTD_FMT_VAL_0))
{
/* Authenticate with default key for block 3 is successful,
so fill the MAD block of sector 0 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_VAL_1;
/* Write the MAD block */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK;
}
else if((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 67)
&& (NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag ==
PH_FRINFC_MFSTD_FMT_VAL_0))
{
/* Authenticate with default key for block 3 is successful,
so fill the MAD block of sector 64 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 64;
/* Write the MAD block */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK;
}
else
{
/* Not a MAD sector */
NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag =
PH_FRINFC_MFSTD_FMT_VAL_0;
/* Write the MAD block */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR;
}
break;
case PH_FRINFC_MFSTD_FMT_AUTH_KEYB:
if((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_1) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_2) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_64) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_65) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_66))
{
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk;
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK;
}
else
{
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk =
PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK;
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR;
}
break;
case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB:
if((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_1) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_2) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_64) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_65) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_66))
{
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk;
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK;
}
else
{
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk =
PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK;
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR;
}
break;
case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY:
case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY:
default:
if((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_66) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_2))
{
/* Updating the MAD block is complete */
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk =
PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK;
/* If Mifare 4k card, write the TLV */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_TLV;
}
else
{
/* Depending on the sector trailer, check the access bit */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_RD_SECT_TR;
}
break;
}
/* Call read, write or authenticate */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus;
/* If default key A is used for authentication and if write fails, then try to
authenticate using key B*/
if(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState ==
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY)
{
/* Change the state to authentication */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* internal authenticate state = key B */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_KEYB;
/* Now call authenticate */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
else
{
Result = phFriNfc_MfStd_H_ProWrSectTr(NdefSmtCrdFmt);
}
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL},
index = PH_FRINFC_MFSTD_FMT_VAL_1,
SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0;
uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1;
/* Calculate sector index */
SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC;
/* Depending on the sector trailer, check the access bit */
memcompare = phFriNfc_MfStd_H_ChkAcsBit(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock,
NdefSmtCrdFmt->SendRecvBuf,
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_AccessBits,
NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_AccessBits);
/* Check the sector for ndef compliance */
NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = (uint8_t)
((memcompare != PH_FRINFC_MFSTD_FMT_VAL_0)?
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL:
PH_FRINFC_MFSTD_FMT_NDEF_COMPL);
/* Increment the current block */
PH_FRINFC_MFSTD_FMT_CUR_BLK_INC();
SectIndex++;
if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK)
{
PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD();
}
else
{
/* Set the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* Set the authenticate state */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;
/* Start authentication */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL},
index = PH_FRINFC_MFSTD_FMT_VAL_1,
SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0;
uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1;
/* Calculate sector index */
SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC;
/* Sector is ndef compliance */
NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = (uint8_t)
((NdefSmtCrdFmt->FmtProcStatus != NFCSTATUS_SUCCESS)?
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL:
PH_FRINFC_MFSTD_FMT_NDEF_COMPL);
/* Increment the current block */
PH_FRINFC_MFSTD_FMT_CUR_BLK_INC();
SectIndex++;
if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK)
{
PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD();
}
else
{
/* Set the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* Set the authenticate state */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;
/* Start authentication */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
return Result;
}
static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo,
const uint8_t *RecvBuf,
const uint8_t AcsBits1[],
const uint8_t AcsBits2[])
{
uint32_t mem = PH_FRINFC_MFSTD_FMT_VAL_0;
/* Compare the access bits read from the sector trailer */
mem = (uint32_t)(((BlockNo == PH_FRINFC_MFSTD_FMT_VAL_3) ||
(BlockNo == 67))?
phFriNfc_MfStd_MemCompare((void*)&RecvBuf[PH_FRINFC_MFSTD_FMT_VAL_6],
(void*)AcsBits1,
PH_FRINFC_MFSTD_FMT_VAL_3):
phFriNfc_MfStd_MemCompare((void*)&RecvBuf[PH_FRINFC_MFSTD_FMT_VAL_6],
(void*)AcsBits2,
PH_FRINFC_MFSTD_FMT_VAL_3));
return mem;
}
static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/* Fill send buffer and send length */
phFriNfc_MfStd_H_FillSendBuf(NdefSmtCrdFmt,
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock);
/* Call ovrhal transceive */
Result = phFriNfc_MfStd_H_Transceive(NdefSmtCrdFmt);
return Result;
}
static void phFriNfc_MfStd_H_ChangeAuthSt(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
uint8_t SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0;
if( NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState ==
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)
{
/* Calculate sector index */
SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC;
/* Check the sector for ndef compliance */
NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] =
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL;
PH_FRINFC_MFSTD_FMT_CUR_BLK_INC();
}
PH_FRINFC_MFSTD_FMT_NXT_AUTH_STATE();
}
static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes,
uint8_t Sector[])
{
uint8_t count = PH_FRINFC_MFSTD_FMT_VAL_0,
NdefComplSectMax = PH_FRINFC_MFSTD_FMT_VAL_0,
NdefComplSectTemp = PH_FRINFC_MFSTD_FMT_VAL_1,
SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0,
MaxCont = PH_FRINFC_MFSTD_FMT_VAL_0,
MaxSect = PH_FRINFC_MFSTD_FMT_VAL_0;
/* Get the maximum sector depending on the sector */
MaxSect = ((CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)?
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K:
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K);
/* Sector index */
NdefComplSectTemp = SectIndex = PH_FRINFC_MFSTD_FMT_VAL_1;
/* Check the sector index depending on the card type */
while(((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) &&
(CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) ||
((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) &&
(CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)))
{
if (Sector[SectIndex] ==
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL)
{
if (MaxCont > count)
{
/* Store the maximum contiguous */
NdefComplSectMax = NdefComplSectTemp;
count = MaxCont;
}
MaxCont = PH_FRINFC_MFSTD_FMT_VAL_0;
/* Increment the sector index */
PH_FRINFC_MFSTD_FMT_INCR_SECT;
/* Get the next compliant sector */
NdefComplSectTemp = SectIndex;
}
else
{
/* Increment the sector index */
PH_FRINFC_MFSTD_FMT_INCR_SECT;
}
MaxCont ++;
}
if (MaxCont > count)
{
/* Store the maximum contiguous */
NdefComplSectMax = NdefComplSectTemp;
count = MaxCont;
}
/* Set the sector value has non ndef compliant which are not present with
contiguous ndef compliant sectors */
if((((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_1)) && (CardTypes
== PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)) ||
((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)) && (CardTypes
== PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD))) &&
((NdefComplSectMax > PH_FRINFC_MFSTD_FMT_VAL_0) &&
(NdefComplSectMax < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2))))
{
(void)memset(&Sector[PH_FRINFC_MFSTD_FMT_VAL_1],
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
(NdefComplSectMax - PH_FRINFC_MFSTD_FMT_VAL_1));
(void)memset(&Sector[(NdefComplSectMax + count)],
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
(MaxSect - (NdefComplSectMax + count)));
}
}
static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock)
{
case PH_FRINFC_MFSTD_FMT_VAL_1:
/* MAD blocks, still not completed */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK;
/* MAD block number 2 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_VAL_2;
break;
case PH_FRINFC_MFSTD_FMT_VAL_2:
/* Now write to MAD block is completed */
NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag =
PH_FRINFC_MFSTD_FMT_VAL_1;
/* Now write the sector trailer, so change the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR;
/* MAD block number 3 = Sector trailer */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_VAL_3;
break;
case 64:
/* MAD blocks, still not completed */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 65;
break;
case 65:
/* MAD blocks, still not completed */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 66;
break;
case 66:
default:
/* Now write to MAD block is completed */
NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag =
PH_FRINFC_MFSTD_FMT_VAL_1;
/* Now write the sector trailer, so change the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 67;
break;
}
/* Write the block */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus;
uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL},
index = PH_FRINFC_MFSTD_FMT_VAL_1;
uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1;
if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 67) &&
(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState ==
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB))
{
/* Error in the MAD sector 16, so the remaining sector
information cant be updated */
(void)memset(&NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[16],
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
(PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K - 16));
PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD();
}
else if(((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >
PH_FRINFC_MFSTD_FMT_VAL_3) &&
(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState !=
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)) ||
((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock ==
PH_FRINFC_MFSTD_FMT_VAL_3) &&
(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState <
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)))
{
/* Authenticate failed, so disconnect, poll and connect */
Result = phFriNfc_MfStd_H_CallDisCon(NdefSmtCrdFmt,
Result);
}
else
{
if (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock ==
PH_FRINFC_MFSTD_FMT_VAL_3)
{
(void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl,
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K);
}
}
return Result;
}
static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk)
{
case PH_FRINFC_MFSTD_FMT_MAD_BLK_1:
/* Write the next MAD Block */
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t)
PH_FRINFC_MFSTD_FMT_MAD_BLK_2;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_MAD_BLK_2;
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_2:
case PH_FRINFC_MFSTD_FMT_MAD_BLK_66:
if((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) ||
(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock ==
PH_FRINFC_MFSTD_FMT_MAD_BLK_66))
{
/* Get the block from where the TLV has to be written */
phFriNfc_MfStd_H_BlkNoToWrTLV(NdefSmtCrdFmt);
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =
PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY;
}
else
{
/* Write the next MAD Block */
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t)
PH_FRINFC_MFSTD_FMT_MAD_BLK_64;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_MAD_BLK_64;
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB;
}
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_64:
/* Write the next MAD Block */
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t)
PH_FRINFC_MFSTD_FMT_MAD_BLK_65;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_MAD_BLK_65;
break;
case PH_FRINFC_MFSTD_FMT_MAD_BLK_65:
default:
/* Write the next MAD Block */
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t)
PH_FRINFC_MFSTD_FMT_MAD_BLK_66;
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =
PH_FRINFC_MFSTD_FMT_MAD_BLK_66;
break;
}
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
return Result;
}
static void phFriNfc_MfStd_H_StrNdefData( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
uint8_t SectIndex = PH_FRINFC_MFSTD_FMT_VAL_1,
index = PH_FRINFC_MFSTD_FMT_VAL_0;
(void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk,
0x00,
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K);
/* Zeroth sector of the Mifare card is MAD sector, CRC is 0x14 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[PH_FRINFC_MFSTD_FMT_VAL_0] = 0x14;
/* Info byte is 0x01, because the NDEF application is written and as per the MAD spec,
the value for miscellaneous application is 0x01 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[PH_FRINFC_MFSTD_FMT_VAL_1] = 0x01;
if(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)
{
/* If 4k card then sector number 16 is MAD sector, CRC is 0xE8 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[32] = 0xE8;
/* Info byte is 0x01, because the NDEF application is written and
as per the MAD spec,
the value for miscellaneous application is 0x01 */
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[33] = 0x01;
}
/* NDEF information has to be updated from */
index = PH_FRINFC_MFSTD_FMT_VAL_2;
/* Depending on the card type, check the sector index */
while (((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) &&
(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) ||
((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) &&
(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)))
{
/* Is the sector ndef compliant? */
if(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] ==
PH_FRINFC_MFSTD_FMT_NDEF_COMPL)
{
/* Ndef compliant sector, update the MAD sector array
in the context with values 0x03 and 0xE1
0x03 and 0xE1 is NDEF information in MAD sector */
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] =
PH_FRINFC_MFSTD_FMT_NDEF_INFO1;
index++;
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] =
PH_FRINFC_MFSTD_FMT_NDEF_INFO2;
index++;
}
else
{
/* Not a Ndef compliant sector, update the MAD sector array
in the context with values 0x00 and 0x00
0x00 and 0x00 is NDEF information in MAD sector */
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 0x00;
index++;
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 0x00;
index++;
}
/* Go to next sector */
SectIndex++;
/* is the sector, a MAD sector 16? */
if(SectIndex == PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K)
{
/* MAD sector number 16, so skip this sector */
SectIndex = SectIndex + PH_FRINFC_MFSTD_FMT_VAL_1;
index = index + PH_FRINFC_MFSTD_FMT_VAL_2;
}
}
}
static void phFriNfc_MfStd_H_BlkNoToWrTLV( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
uint8_t SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_1;
while (((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) &&
(NdefSmtCrdFmt->CardType == (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) ||
((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) &&
(NdefSmtCrdFmt->CardType == (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)))
{
if (NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] ==
(uint8_t)PH_FRINFC_MFSTD_FMT_NDEF_COMPL)
{
/* Get the first NFC forum sector's block */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = (uint16_t)
(((SectIndex & 0xE0) >= 32)?
(128 + ((SectIndex % 32) * 16)):
(SectIndex * (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_4));
/* Break out of the loop */
SectIndex += (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K;
}
SectIndex++;
}
}
static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus;
uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL},
index = PH_FRINFC_MFSTD_FMT_VAL_1,
SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0;
uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1;
/* If default key A is used for authentication and if write fails, then try to
authenticate using key B*/
if(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState ==
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY)
{
/* Change the state to authentication */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* internal authenticate state = key B */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_KEYB;
/* Now call authenticate */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
else
{
/* Calculate sector index */
SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC;
/* Sector is ndef compliance */
NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = (uint8_t)
((NdefSmtCrdFmt->FmtProcStatus != NFCSTATUS_SUCCESS)?
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL:
PH_FRINFC_MFSTD_FMT_NDEF_COMPL);
/* Increment the current block */
PH_FRINFC_MFSTD_FMT_CUR_BLK_INC();
SectIndex++;
if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK)
{
PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD();
}
else
{
/* Set the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;
/* Set the authenticate state */
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;
/* Start authentication */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
}
return Result;
}
static int phFriNfc_MfStd_MemCompare( void *s1, void *s2, unsigned int n )
{
int8_t diff = 0;
int8_t *char_1 =(int8_t *)s1;
int8_t *char_2 =(int8_t *)s2;
if(NULL == s1 || NULL == s2)
{
PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare");
}
else
{
for(;((n>0)&&(diff==0));n--,char_1++,char_2++)
{
diff = *char_1 - *char_2;
}
}
return (int)diff;
}
#ifdef UNIT_TEST
#include <phUnitTestNfc_MifStdFormat_static.c>
#endif