| /* |
| * 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; |
| } |
| |