/*
* 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_SmtCrdFmt.c
* \brief This component encapsulates different smart and simple tag formatting functionalities,
* for the mapping layer.
*
* Project: NFC-FRI
*
* $Date: Mon Dec 13 14:14:13 2010 $
* $Author: ing02260 $
* $Revision: 1.9 $
* $Aliases: $
*
*/
#ifndef PH_FRINFC_CARD_FORMAT_DISABLED
#include <phNfcTypes.h>
#include <phFriNfc_OvrHal.h>
#include <phFriNfc_SmtCrdFmt.h>
#ifdef DISABLE_FORMAT
#include <phFriNfc_TopazFormat.h>
#endif /* #ifdef DISABLE_FORMAT */
#include <phFriNfc_MifULFormat.h>
#include <phFriNfc_DesfireFormat.h>
#include <phFriNfc_MifStdFormat.h>
#ifndef PH_FRINFC_FMT_ISO15693_DISABLED
#include <phFriNfc_ISO15693Format.h>
#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */
/*! \ingroup grp_file_attributes
* \name NDEF Mapping
*
* File: \ref phFriNfc_CardFormatFunctions.c
*
*/
/*@{*/
// file versions
/*@}*/
void phFriNfc_SmtCrdFmt_HCrHandler(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
NFCSTATUS Status)
{
/* set the state back to the Reset_Init state*/
NdefSmtCrdFmt->State = PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT;
/* set the completion routine*/
NdefSmtCrdFmt->CompletionRoutine[PH_FRINFC_SMTCRDFMT_CR_FORMAT].
CompletionRoutine(NdefSmtCrdFmt->CompletionRoutine->Context, Status);
}
/*!
* \brief Used to Reset the context variables , before the actual smart card formatting
* procedure.
*
*/
NFCSTATUS phFriNfc_NdefSmtCrd_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
void *LowerDevice,
phHal_sRemoteDevInformation_t *psRemoteDevInfo,
phHal_sDevInputParam_t *psDevInputParam,
uint8_t *SendRecvBuffer,
uint16_t *SendRecvBuffLen)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
uint8_t index;
if ( (SendRecvBuffLen == NULL) || (NdefSmtCrdFmt == NULL) || (psRemoteDevInfo == NULL) ||
(SendRecvBuffer == NULL) || (LowerDevice == NULL) ||
(*SendRecvBuffLen == 0) || (psDevInputParam == NULL) ||
(*SendRecvBuffLen < PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE) )
{
result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER);
}
else
{
/* Initialise the state to Init */
NdefSmtCrdFmt->State = PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT;
for(index = 0;index<PH_FRINFC_SMTCRDFMT_CR;index++)
{
/* Initialise the NdefMap Completion Routine to Null */
NdefSmtCrdFmt->CompletionRoutine[index].CompletionRoutine = NULL;
/* Initialise the NdefMap Completion Routine context to Null */
NdefSmtCrdFmt->CompletionRoutine[index].Context = NULL;
}
/* Lower Device(Always Overlapped HAL Struct initialised in application
is registred in NdefMap Lower Device) */
NdefSmtCrdFmt->LowerDevice = LowerDevice;
/* Remote Device info received from Manual Device Discovery is registered here */
NdefSmtCrdFmt->psRemoteDevInfo = psRemoteDevInfo;
/* Trx Buffer registered */
NdefSmtCrdFmt->SendRecvBuf = SendRecvBuffer;
/* Trx Buffer Size */
NdefSmtCrdFmt->SendRecvLength = SendRecvBuffLen;
/* Register Transfer Buffer Length */
NdefSmtCrdFmt->SendLength = 0;
/* Initialise the Format status flag*/
NdefSmtCrdFmt->FmtProcStatus = 0;
/* Reset the Card Type */
NdefSmtCrdFmt->CardType = 0;
/* Reset MapCompletion Info*/
NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = NULL;
NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NULL;
#ifndef PH_FRINFC_FMT_TOPAZ_DISABLED
phFriNfc_Topaz_Reset(NdefSmtCrdFmt);
#endif /* PH_FRINFC_FMT_TOPAZ_DISABLED */
#ifndef PH_FRINFC_FMT_DESFIRE_DISABLED
/*Reset Desfire Cap Container elements*/
phFriNfc_Desfire_Reset(NdefSmtCrdFmt);
#endif /* PH_FRINFC_FMT_DESFIRE_DISABLED */
#ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED
/*Reset Mifare Standard Container elements*/
NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam = psDevInputParam;
phFriNfc_MfStd_Reset(NdefSmtCrdFmt);
#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */
#ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED
phFriNfc_MfUL_Reset(NdefSmtCrdFmt);
#endif /* #ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED */
#ifndef PH_FRINFC_FMT_ISO15693_DISABLED
phFriNfc_ISO15693_FmtReset (NdefSmtCrdFmt);
#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */
#ifdef PHFRINFC_OVRHAL_MOCKUP
/*Reset Desfire Cap Container elements*/
// phFriNfc_Mockup_H_Reset(NdefSmtCrdFmt);
#endif /* PHFRINFC_OVRHAL_MOCKUP */
}
return (result);
}
/*!
* \brief Completion Routine initialisation
*
*/
NFCSTATUS phFriNfc_NdefSmtCrd_SetCR(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
uint8_t FunctionID,
pphFriNfc_Cr_t CompletionRoutine,
void *CompletionRoutineContext)
{
NFCSTATUS status = NFCSTATUS_SUCCESS;
if ((NdefSmtCrdFmt == NULL) || (FunctionID >= PH_FRINFC_SMTCRDFMT_CR) ||
(CompletionRoutine == NULL) || (CompletionRoutineContext == NULL))
{
status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER);
}
else
{
/* Register the application callback with the NdefMap Completion Routine */
NdefSmtCrdFmt->CompletionRoutine[FunctionID].CompletionRoutine = CompletionRoutine;
/* Register the application context with the NdefMap Completion Routine context */
NdefSmtCrdFmt->CompletionRoutine[FunctionID].Context = CompletionRoutineContext;
}
return status;
}
#ifdef FRINFC_READONLY_NDEF
NFCSTATUS
phFriNfc_NdefSmtCrd_ConvertToReadOnly (
phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
{
NFCSTATUS result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_PARAMETER);
uint8_t sak = 0;
if((NdefSmtCrdFmt != NULL)
&& (NdefSmtCrdFmt->CompletionRoutine->CompletionRoutine != NULL)
&& (NdefSmtCrdFmt->CompletionRoutine->Context != NULL))
{
sak = NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak;
switch (NdefSmtCrdFmt->psRemoteDevInfo->RemDevType)
{
case phHal_eMifare_PICC:
{
if (0x00 == sak)
{
result = phFriNfc_MfUL_ConvertToReadOnly (NdefSmtCrdFmt);
}
else
{
/* MIFARE classic 1k/4k is not supported */
result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
}
break;
}
case phHal_eISO14443_A_PICC:
{
result = phFriNfc_Desfire_ConvertToReadOnly (NdefSmtCrdFmt);
break;
}
default :
{
/* Remote device is not recognised.
Probably not NDEF compliant */
result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
break;
}
}
}
return result;
}
#endif /* #ifdef FRINFC_READONLY_NDEF */
/*!
* \brief Used to format the different smart cards.
*
*/
NFCSTATUS phFriNfc_NdefSmtCrd_Format( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, const uint8_t *ScrtKeyB )
{
/* Component ID needs to be changed */
NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_PARAMETER);
uint8_t sak = 0;
/* Check for the correct context structure */
if((NdefSmtCrdFmt != NULL) &&
(NdefSmtCrdFmt->CompletionRoutine->CompletionRoutine != NULL) &&
(NdefSmtCrdFmt->CompletionRoutine->Context != NULL))
{
#ifdef PH_HAL4_ENABLE
/* SAK (Select response) */
sak = NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak;
/* Depending on the Opmodes, call the respective card functions */
switch ( NdefSmtCrdFmt->psRemoteDevInfo->RemDevType )
#else
/* SAK (Select response) */
sak = NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.CardInfo106.
Startup106.SelRes;
/* Depending on the Opmodes, call the respective card functions */
switch ( NdefSmtCrdFmt->psRemoteDevInfo->OpMode )
#endif /* #ifdef PH_HAL4_ENABLE */
{
#ifdef PH_HAL4_ENABLE
case phHal_eMifare_PICC :
#else
case phHal_eOpModesMifare :
#endif /* #ifdef PH_HAL4_ENABLE */
/* Remote device is Mifare card . Check for Mifare
NDEF compliance */
if(0x00 == sak)
{
#ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED
/* The SAK/Sel_Res says the card is of the type
Mifare UL */
NdefSmtCrdFmt->CardType = PH_FRINFC_SMTCRDFMT_MIFARE_UL_CARD;
if (NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.UidLength == 7 &&
NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Uid[0] == 0x04)
{
Result = phFriNfc_MfUL_Format( NdefSmtCrdFmt);
}
else
{
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
}
#else
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* #ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED */
}
else if((0x08 == (sak & 0x18)) ||
(0x18 == (sak & 0x18)))
{
#ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED
NdefSmtCrdFmt->CardType = (uint8_t)
(((sak & 0x18) == 0x08)?
PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD:
PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD);
/* The SAK/Sel_Res says the card is of the type
Mifare standard */
Result = phFriNfc_MfStd_Format( NdefSmtCrdFmt, ScrtKeyB);
#else
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* #ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED */
}
else
{
/* Invalid Mifare card, as the remote device
info - opmode says its a Mifare card but,
The SAK/Sel_Res is wrong */
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
}
break;
#ifdef PH_HAL4_ENABLE
case phHal_eISO14443_A_PICC :
#else
case phHal_eOpModesISO14443_4A :
#endif /* #ifdef PH_HAL4_ENABLE */
/* Remote device is Desfire card . Check for Desfire
NDEF compliancy */
if(0x20 == (sak & 0xFF))
{
#ifndef PH_FRINFC_FMT_DESFIRE_DISABLED
NdefSmtCrdFmt->CardType = PH_FRINFC_SMTCRDFMT_ISO14443_4A_CARD;
/* The SAK/Sel_Res says the card is of the type
ISO14443_4A */
Result = phFriNfc_Desfire_Format(NdefSmtCrdFmt);
#else
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* #ifndef PH_FRINFC_FMT_DESFIRE_DISABLED */
}
else
{
/* Invalid Desfire card, as the remote device
info - opmode says its a desfire card but,
The SAK/Sel_Res is wrong */
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
}
break;
#ifdef PH_HAL4_ENABLE
case phHal_eJewel_PICC :
#else
case phHal_eOpModesJewel :
#endif /* #ifdef PH_HAL4_ENABLE */
/* Remote device is Topaz card . Check for Topaz
NDEF compliancy */
if(0xC2 == sak)
{
#ifndef PH_FRINFC_FMT_TOPAZ_DISABLED
NdefSmtCrdFmt->CardType = PH_FRINFC_SMTCRDFMT_TOPAZ_CARD;
/* The SAK/Sel_Res says the card is of the type
ISO14443_4A */
Result = phFriNfc_Topaz_Format(NdefSmtCrdFmt);
#else
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* #ifndef PH_FRINFC_FMT_TOPAZ_DISABLED */
}
else
{
/* Invalid Topaz card, as the remote device
info - opmode says its a desfire card but,
The SAK/Sel_Res is wrong */
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
}
break;
#ifdef PHFRINFC_OVRHAL_MOCKUP
case phHal_eOpModesMockup :
/*Set the OpMode Ttype Flag*/
NdefSmtCrdFmt->OpModeType[0] = phHal_eOpModesMockup;
NdefSmtCrdFmt->OpModeType[1] = phHal_eOpModesArrayTerminator;
//Result = phFriNfc_Mockup_ChkNdef(NdefSmtCrdFmt);
break;
#endif /* PHFRINFC_OVRHAL_MOCKUP */
#ifndef PH_FRINFC_FMT_ISO15693_DISABLED
case phHal_eISO15693_PICC:
{
Result = phFriNfc_ISO15693_Format (NdefSmtCrdFmt);
break;
}
#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */
default :
/* Remote device is not recognised.
Probably not NDEF compliant */
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
break;
}
}
return Result;
}
/*!
* \brief Handles different request and responses from the integration layer.
*
*/
void phFriNfc_NdefSmtCrd_Process(void *Context,
NFCSTATUS Status)
{
if ( Context != NULL )
{
phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
#ifdef PH_HAL4_ENABLE
switch ( NdefSmtCrdFmt->psRemoteDevInfo->RemDevType )
#else
switch ( NdefSmtCrdFmt->psRemoteDevInfo->OpMode )
#endif /* #ifdef PH_HAL4_ENABLE */
{
#ifdef PH_HAL4_ENABLE
case phHal_eMifare_PICC :
#else
case phHal_eOpModesMifare :
#endif /* #ifdef PH_HAL4_ENABLE */
if((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) ||
(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD))
{
#ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED
/* Remote device is Mifare Standard card */
phFriNfc_MfStd_Process(NdefSmtCrdFmt,Status);
#else /* PH_FRINFC_FMT_MIFARESTD_DISABLED*/
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* PH_FRINFC_FMT_MIFARESTD_DISABLED*/
}
else
{
#ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED
/* Remote device is Mifare UL card */
phFriNfc_MfUL_Process(NdefSmtCrdFmt,Status);
#else /* PH_FRINFC_FMT_MIFAREUL_DISABLED*/
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* PH_FRINFC_FMT_MIFAREUL_DISABLED*/
}
break;
#ifdef PH_HAL4_ENABLE
case phHal_eISO14443_A_PICC :
#else
case phHal_eOpModesISO14443_4A :
#endif /* #ifdef PH_HAL4_ENABLE */
#ifndef PH_FRINFC_FMT_DESFIRE_DISABLED
/* Remote device is Desfire card */
phFriNfc_Desf_Process(NdefSmtCrdFmt, Status);
#else /* PH_FRINFC_FMT_DESFIRE_DISABLED*/
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* PH_FRINFC_FMT_DESFIRE_DISABLED*/
break;
#ifdef PH_HAL4_ENABLE
case phHal_eJewel_PICC :
#else
case phHal_eOpModesJewel:
#endif /* #ifdef PH_HAL4_ENABLE */
#ifndef PH_FRINFC_FMT_TOPAZ_DISABLED
/* Remote device is Topaz Smart card */
phFriNfc_Topaz_Process(NdefSmtCrdFmt, Status);
#else /* PH_FRINFC_FMT_TOPAZ_DISABLED*/
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
#endif /* PH_FRINFC_FMT_TOPAZ_DISABLED*/
break;
#ifndef PH_FRINFC_FMT_ISO15693_DISABLED
case phHal_eISO15693_PICC :
{
phFriNfc_ISO15693_FmtProcess (NdefSmtCrdFmt, Status);
break;
}
#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */
#ifdef PHFRINFC_OVRHAL_MOCKUP
case phHal_eOpModesMockup:
/* Remote device is Desfire card */
//phFriNfc_Mockup_Process(NdefSmtCrdFmt, Status);
break;
#endif /* PHFRINFC_OVRHAL_MOCKUP*/
default :
/* Remote device opmode not recognised.
Probably not NDEF compliant */
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
NFCSTATUS_INVALID_REMOTE_DEVICE);
/* set the state back to the Reset_Init state*/
NdefSmtCrdFmt->State = PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT;
/* set the completion routine*/
NdefSmtCrdFmt->CompletionRoutine[PH_FRINFC_SMTCRDFMT_CR_INVALID_OPE].
CompletionRoutine(NdefSmtCrdFmt->CompletionRoutine->Context, Status);
break;
}
}
else
{
Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,\
NFCSTATUS_INVALID_PARAMETER);
/* The control should not come here. As Context itself is NULL ,
Can't call the CR*/
}
}
#endif /* PH_FRINFC_CARD_FORMAT_DISABLED */