blob: 894d455d1777dfc1bc69f4f649069741d42c7597 [file] [log] [blame]
/*
* 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_MifULFormat.c
* \brief NFC Ndef Formatting For Mifare ultralight card.
*
* Project: NFC-FRI
*
* $Date: Fri Oct 23 12:00:05 2009 $
* $Author: ing02260 $
* $Revision: 1.8 $
* $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_MifULFormat.h>
#include <phFriNfc_OvrHal.h>
/*! \ingroup grp_file_attributes
* \name NDEF Mapping
*
* File: \ref phFriNfc_MifULFormat.c
*
*/
/*@{*/
#define PHFRINFCMIFULFORMAT_FILEREVISION "$Revision: 1.8 $"
#define PHFRINFCMIFULFORMAT_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 UL. This function calls the
* transceive function
*/
static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the
* read or write operation
*/
static NFCSTATUS phFriNfc_MfUL_H_WrRd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function fills the
* send buffer for transceive function
*/
static void phFriNfc_MfUL_H_fillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
uint8_t BlockNo);
/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process
* the read bytes
*/
static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process the
* OTP bytes written
*/
static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
static int MemCompare1 ( void *s1, void *s2, unsigned int n );
/*The function does a comparision of two strings and returns a non zero value
if two strings are unequal*/
static int MemCompare1 ( 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;
}
void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
(void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
OTPByte,
sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
}
NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
(void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
OTPByte,
sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
/* Set the state */
NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RD_16BYTES;
/* Initialise current block to the lock bits block */
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_2;
/* Start authentication */
Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
return Result;
}
void phFriNfc_MfUL_Process(void *Context,
NFCSTATUS Status)
{
phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
if(Status == NFCSTATUS_SUCCESS)
{
switch(NdefSmtCrdFmt->State)
{
case PH_FRINFC_MFUL_FMT_RD_16BYTES:
Status = phFriNfc_MfUL_H_ProRd16Bytes(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
Status = phFriNfc_MfUL_H_ProWrOTPBytes(NdefSmtCrdFmt);
break;
case PH_FRINFC_MFUL_FMT_WR_TLV:
#ifdef PH_NDEF_MIFARE_ULC
if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
{
/* Write NDEF TLV in block number 5 */
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
PH_FRINFC_MFUL_FMT_VAL_5;
/* Card already have the OTP bytes so write TLV */
NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV1;
Status = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
}
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
break;
#ifdef PH_NDEF_MIFARE_ULC
case PH_FRINFC_MFUL_FMT_WR_TLV1:
break;
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
default:
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_DEVICE_REQUEST);
break;
}
}
/* Status is not success then call completion routine */
if(Status != NFCSTATUS_PENDING)
{
phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status);
}
}
static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/* Fill the send buffer */
phFriNfc_MfUL_H_fillSendBuf(NdefSmtCrdFmt,
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock);
/* Call transceive */
Result = phFriNfc_MfUL_H_Transceive(NdefSmtCrdFmt);
return Result;
}
static NFCSTATUS phFriNfc_MfUL_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 void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
uint8_t BlockNo)
{
#ifdef PH_NDEF_MIFARE_ULC
uint8_t NDEFTLV1[4] = {0x01, 0x03, 0xA0, 0x10};
uint8_t NDEFTLV2[4] = {0x44, 0x03, 0x00, 0xFE};
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
uint8_t NDEFTLV[4] = {0x03, 0x00, 0xFE, 0x00};
/* First byte for send buffer is always the block number */
NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_0] = (uint8_t)BlockNo;
switch(NdefSmtCrdFmt->State)
{
case PH_FRINFC_MFUL_FMT_RD_16BYTES:
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
#else
/* Read command */
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
#endif /* #ifdef PH_HAL4_ENABLE */
/* Send length for read command is always one */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
break;
case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
/* Send length for read command is always Five */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
/* Write command */
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
#endif /* #ifdef PH_HAL4_ENABLE */
/* Copy the OTP bytes */
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
PH_FRINFC_MFUL_FMT_VAL_4);
break;
case PH_FRINFC_MFUL_FMT_WR_TLV:
#ifndef PH_NDEF_MIFARE_ULC
default:
#endif /* #ifndef PH_NDEF_MIFARE_ULC */
/* Send length for read command is always Five */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
/* Write command */
#ifdef PH_HAL4_ENABLE
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
#else
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
#endif /* #ifdef PH_HAL4_ENABLE */
/* Copy the NDEF TLV */
#ifdef PH_NDEF_MIFARE_ULC
if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
{
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
NDEFTLV1,
PH_FRINFC_MFUL_FMT_VAL_4);
}
else if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD)
{
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
NDEFTLV,
PH_FRINFC_MFUL_FMT_VAL_4);
}
else
{
}
#else
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
NDEFTLV,
PH_FRINFC_MFUL_FMT_VAL_4);
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
break;
#ifdef PH_NDEF_MIFARE_ULC
case PH_FRINFC_MFUL_FMT_WR_TLV1:
if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
{
/* Send length for write command is always Five */
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
/* Write command */
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
NDEFTLV2,
PH_FRINFC_MFUL_FMT_VAL_4);
}
break;
default:
break;
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
}
}
static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_FORMAT_ERROR);
uint32_t memcompare = PH_FRINFC_MFUL_FMT_VAL_0;
uint8_t ZeroBuf[] = {0x00, 0x00, 0x00, 0x00};
#ifdef PH_NDEF_MIFARE_ULC
uint8_t OTPByteUL[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
uint8_t OTPByteULC[] = PH_FRINFC_MFULC_FMT_OTP_BYTES;
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
/* Check the lock bits (byte number 2 and 3 of block number 2) */
if ((NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_2] ==
PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL) &&
(NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_3] ==
PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL))
{
#ifdef PH_NDEF_MIFARE_ULC
if (NdefSmtCrdFmt->SendRecvBuf[8] == 0x02 &&
NdefSmtCrdFmt->SendRecvBuf[9] == 0x00)
{
NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD;
(void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
OTPByteULC,
sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
}
else if (NdefSmtCrdFmt->SendRecvBuf[8] == 0xFF &&
NdefSmtCrdFmt->SendRecvBuf[9] == 0xFF)
{
NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
(void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
OTPByteUL,
sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
}
else
{
NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
}
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
memcompare = (uint32_t)
MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
PH_FRINFC_MFUL_FMT_VAL_4);
if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
{
/* Write NDEF TLV in block number 4 */
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
PH_FRINFC_MFUL_FMT_VAL_4;
/* Card already have the OTP bytes so write TLV */
NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
}
else
{
/* IS the card new, OTP bytes = {0x00, 0x00, 0x00, 0x00} */
memcompare = (uint32_t)MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
ZeroBuf,
PH_FRINFC_MFUL_FMT_VAL_4);
/* If OTP bytes are Zero then the card is Zero */
if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
{
/* Write OTP bytes in block number 3 */
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
PH_FRINFC_MFUL_FMT_VAL_3;
/* Card already have the OTP bytes so write TLV */
NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_OTPBYTES;
}
}
}
#ifdef PH_NDEF_MIFARE_ULC
if(
((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) ||
(NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES)) &&
((NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) ||
(NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD))
)
#else
if((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) ||
(NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES))
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
{
Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
}
return Result;
}
static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
NFCSTATUS Result = NFCSTATUS_SUCCESS;
/* Card already have the OTP bytes so write TLV */
NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
/* Write NDEF TLV in block number 4 */
NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
PH_FRINFC_MFUL_FMT_VAL_4;
Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
return Result;
}