blob: 7018e81280fd0290a8920ec4eb4b7c8fe19a00b6 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.
*/
/*
* Mifare Standard Format implementation
*/
#include <phFriNfc_MifStdFormat.h>
#include <phNxpExtns_MifareStd.h>
#include <phNfcCompId.h>
#include <phNxpLog.h>
/* Function prototype declarations */
static void phFriNfc_MfStd_H_FillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, uint16_t BlockNo);
static NFCSTATUS phFriNfc_MfStd_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_CallDisCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, NFCSTATUS Status);
static NFCSTATUS phFriNfc_MfStd_H_CallCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ProCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ProAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo, const uint8_t *RecvBuf, const uint8_t AcsBits1[], const uint8_t AcsBits2[]);
static void phFriNfc_MfStd_H_ChangeAuthSt(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes, uint8_t Sector[]);
static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static void phFriNfc_MfStd_H_StrNdefData(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static void phFriNfc_MfStd_H_BlkNoToWrTLV(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static int phFriNfc_MfStd_MemCompare(void *s1, void *s2, unsigned int n );
/*
* Enum definition contains format states
*/
typedef enum Mfc_format_state{
MFC_FORMAT_INIT = 0x00,
MFC_FORMAT_NFC_KEY,
MFC_FORMAT_DEF_KEY,
MFC_FORMAT_INVALID
}MFC_FORMAT_STATE;
/* format key status */
static MFC_FORMAT_STATE FormatKeyState = MFC_FORMAT_INIT;
/*******************************************************************************
**
** Function phFriNfc_MfStd_Reset
**
** Description Resets the component instance to the initial state and initializes the
** internal variables.
**
** Returns none
**
*******************************************************************************/
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 */
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 */
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 */
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 */
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;
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_Format
**
** Description The function initiates and formats the Smart Card.After this formation, remote
** card would be properly initialized and Ndef Compliant.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
/* Initialize current block to the first sector trailer */
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = PH_FRINFC_MFSTD_FMT_VAL_3;
/* Set the authenticate state */
if( MFC_FORMAT_DEF_KEY == FormatKeyState)
{
FormatKeyState = MFC_FORMAT_INIT;
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;
}
else
{
FormatKeyState = MFC_FORMAT_NFC_KEY;
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY; /* Key Chnage for some cards */
}
/* Start authentication */
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);
}
return Result;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_Process
**
** Description Completion Routine: This function is called by the lower layer (OVR HAL)
** when an I/O operation has finished. The internal state machine decides
** whether to call into the lower device again or to complete the process
** by calling into the upper layer's completion routine, stored within this
** component's context (phFriNfc_sNdefSmtCrdFmt_t).
**
** Returns none
**
*******************************************************************************/
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:
Status = phFriNfc_MfStd_H_CallCon(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFSTD_FMT_CON:
if( MFC_FORMAT_DEF_KEY == FormatKeyState)
{
/* retry the format with other key */
Mfc_FormatNdef(current_key,6);
return;
}
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:
if(MFC_FORMAT_NFC_KEY == FormatKeyState)
{
FormatKeyState = MFC_FORMAT_DEF_KEY;
}
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);
}
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_FillSendBuf
**
** Description This function fills the send buffer for transceive function
**
** Returns none
**
*******************************************************************************/
static void phFriNfc_MfStd_H_FillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, uint16_t BlockNo)
{
// void *mem = NULL; /*commented to eliminate unused variable warning*/
uint8_t MADSectTr1k[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K, /* MAD key A,
Access bits and GPB of MAD sector */
MADSectTr2k[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_2K, /* 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;
/* Initialize 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:
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
/* 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 */
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
/* 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)
{
memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
MADSectTr1k,
sizeof(MADSectTr1k));
}
else if (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD)
{
memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],
MADSectTr2k,
sizeof(MADSectTr2k));
}
else
{
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;
}
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 */
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
/* Copy the NDEF message TLV */
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 */
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
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 */
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 */
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16;
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH;
switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk)
{
case PH_FRINFC_MFSTD_FMT_MAD_BLK_1:
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:
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:
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:
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:
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;
}
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_Transceive
**
** Description This function authenticates a block or a sector from the card.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
static NFCSTATUS phFriNfc_MfStd_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/*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_ExtnsTransceive(NdefSmtCrdFmt->pTransceiveInfo,
NdefSmtCrdFmt->Cmd,
NdefSmtCrdFmt->SendRecvBuf,
NdefSmtCrdFmt->SendLength,
NdefSmtCrdFmt->SendRecvLength);
return Result;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_CallDisCon
**
** Description This function calls disconnect.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
Result = phNxNciExtns_MifareStd_Reconnect();
return Result;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_CallCon
**
** Description This function calls reconnect.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
static NFCSTATUS phFriNfc_MfStd_H_CallCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/*Set Ndef State*/
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_CON;
Result = phNxNciExtns_MifareStd_Reconnect();
return Result;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProCon
**
** Description This function shall process the poll call.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
static NFCSTATUS phFriNfc_MfStd_H_ProCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL};
uint8_t 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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProAuth
**
** Description This function shall process the authenticate call.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ErrWrSectTr
**
** Description This function shall process the error status of the writing sector trailer.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProRdSectTr
**
** Description This function shall process the read access bit call.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProWrSectTr
**
** Description This function shall process the write access bit call.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ChkAcsBit
**
** Description This function checks access bits of each sector trailer.
**
** Returns compare value
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_WrRdAuth
**
** Description This function writes sector trailer using the block number.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ChangeAuthSt
**
** Description This function changes authentication state and change the block number if required.
**
** Returns none
**
*******************************************************************************/
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();
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_NdefComplSect
**
** Description This function finds contiguous ndef compliant blocks.
**
** Returns none
**
*******************************************************************************/
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:
((CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD)?
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K:
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))||
((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K) &&
(CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_2K_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)) ||
((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)) && (CardTypes
== PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD)))&&
((NdefComplSectMax > PH_FRINFC_MFSTD_FMT_VAL_0) &&
(NdefComplSectMax < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2))))
{
memset(&Sector[PH_FRINFC_MFSTD_FMT_VAL_1],
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
(NdefComplSectMax - PH_FRINFC_MFSTD_FMT_VAL_1));
memset(&Sector[(NdefComplSectMax + count)],
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
(MaxSect - (NdefComplSectMax + count)));
}
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProWrMADBlk
**
** Description This function writes the finds MAD block values.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProErrAuth
**
** Description This function shall process the error status of the authentication.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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 can't be updated
*/
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)
{
memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl,
PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL,
PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K);
}
}
return Result;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ProUpdMADBlk
**
** Description This function shall process the error status of the writing sector trailer.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_StrNdefData
**
** Description This function shall store ndef compliant in the MAD array
** which will be later used for updating the MAD sector.
**
** Returns none
**
*******************************************************************************/
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;
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) ||
(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_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)) ||
((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K) &&
(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_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;
}
}
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_BlkNoToWrTLV
**
** Description This function shall find the ndef compliant
** and calculate the block number to write the NDEF TLV.
**
** Returns none
**
*******************************************************************************/
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)) ||
((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K) &&
(NdefSmtCrdFmt->CardType == (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_2K_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++;
}
return;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_H_ErrRdSectTr
**
** Description This function shall process the error status of the reading sector trailer.
**
** Returns NFCSTATUS_PENDING if successful
** Other values if an error has occurred
**
*******************************************************************************/
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;
}
/*******************************************************************************
**
** Function phFriNfc_MfStd_MemCompare
**
** Description This function shall process memory comparison.
**
** Returns 0 if memory is same
** Not 0 if different
**
*******************************************************************************/
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)
{
NXPLOG_EXTNS_E("NULL pointer passed to memcompare");
}
else
{
for(;((n>0)&&(diff==0));n--,char_1++,char_2++)
{
diff = *char_1 - *char_2;
}
}
return (int)diff;
}