diff options
author | Nick Pelly <npelly@google.com> | 2010-09-23 12:47:58 -0700 |
---|---|---|
committer | Nick Pelly <npelly@google.com> | 2010-09-23 13:53:18 -0700 |
commit | 5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a (patch) | |
tree | 190f9251c6db03d3550ec7f30b51a2561c01d9cf /src/phFriNfc_DesfireMap.c | |
parent | 4ff7c86a2c706b150078274455406f1b04966e1a (diff) | |
download | libnfc-nxp-5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a.tar.gz |
Initial libnfc checkin
Source: Trusted_NFC_Device_Host_AA03.01e02_google.zip code drop (23-Sep-2010)
Change-Id: Ie47f18423f949a8d3e0815d13f55c814312add24
Signed-off-by: Nick Pelly <npelly@google.com>
Diffstat (limited to 'src/phFriNfc_DesfireMap.c')
-rw-r--r-- | src/phFriNfc_DesfireMap.c | 1671 |
1 files changed, 1671 insertions, 0 deletions
diff --git a/src/phFriNfc_DesfireMap.c b/src/phFriNfc_DesfireMap.c new file mode 100644 index 0000000..6667bb0 --- /dev/null +++ b/src/phFriNfc_DesfireMap.c @@ -0,0 +1,1671 @@ +/* + * 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_Desfire.c +* \brief This component encapsulates read/write/check ndef/process functionalities, +* for the Desfire Card. +* +* Project: NFC-FRI +* +* $Date: Thu Jul 23 13:45:00 2009 $ +* $Author: ing07336 $ +* $Revision: 1.10 $ +* $Aliases: NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,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 $ +* +*/ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + +#include <phFriNfc_OvrHal.h> +#include <phFriNfc_DesfireMap.h> +#include <phFriNfc_MapTools.h> + + +/*! \ingroup grp_file_attributes +* \name NDEF Mapping +* +* File: \ref phFriNfc_Desfire.c +* +*/ +/*@{*/ +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.10 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,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 $" + +/*@}*/ + +/*@}*/ + +/*! + * \name Desfire Mapping - Helper Functions + * + */ +/*@{*/ + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function specifies + * the card is a Desfire card or not. + */ +static NFCSTATUS phFriNfc_Desfire_SelectSmartTag( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is used + * to selct a file in the card. + */ +static NFCSTATUS phFriNfc_Desfire_SelectFile ( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is to + * read the card. + */ +static NFCSTATUS phFriNfc_Desfire_ReadBinary( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is to + * write to the card. + */ +static NFCSTATUS phFriNfc_Desfire_UpdateBinary( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is to + * update the capability container of the card. + */ +static NFCSTATUS phFriNfc_Desfire_Update_SmartTagCapContainer( phFriNfc_NdefMap_t *NdefMap); + + +/* Completion Helper*/ +static void phFriNfc_Desfire_HCrHandler( phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status); + +/* Calculates the Le Bytes for Read Operation*/ +static uint32_t phFriNfc_Desfire_HGetLeBytes( phFriNfc_NdefMap_t *NdefMap); + +static NFCSTATUS phFriNfc_Desf_HChkAndParseTLV( phFriNfc_NdefMap_t *NdefMap, + uint8_t BuffIndex); + +static NFCSTATUS phFriNfc_Desfire_HSetGet_NLEN( phFriNfc_NdefMap_t *NdefMap); + +static void phFriNfc_Desfire_HProcReadData( phFriNfc_NdefMap_t *NdefMap); + +static void phFriNfc_Desfire_HChkNDEFFileAccessRights( phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HSendTransCmd(phFriNfc_NdefMap_t *NdefMap,uint8_t SendRecvLen); + +#ifdef PH_HAL4_ENABLE + +#else + +/* Following are the API's are used to get the version of the desfire card*/ +static NFCSTATUS phFriNfc_Desfire_HGetHWVersion(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HGetSWVersion(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HGetUIDDetails(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HUpdateVersionDetails(const phFriNfc_NdefMap_t *NdefMap); + +#endif /* #ifdef PH_HAL4_ENABLE */ + +#ifdef PH_HAL4_ENABLE + +#else + +static NFCSTATUS phFriNfc_Desfire_HGetHWVersion(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + /*set the state*/ + NdefMap->State = PH_FRINFC_DESF_STATE_GET_HW_VERSION; + + /* Helper routine to wrap the native desfire cmds*/ + PH_FRINFC_DESF_ISO_NATIVE_WRAPPER(); + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + + return (status); +} + +static NFCSTATUS phFriNfc_Desfire_HGetSWVersion(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + if( ( NdefMap->SendRecvBuf[*(NdefMap->SendRecvLength)- 1] == PH_FRINFC_DESF_NATIVE_GETVER_RESP) ) + { + /*set the state*/ + NdefMap->State = PH_FRINFC_DESF_STATE_GET_SW_VERSION; + + /* Helper routine to wrap the native desfire commands*/ + PH_FRINFC_DESF_ISO_NATIVE_WRAPPER(); + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + } +#ifdef PH_HAL4_ENABLE + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } +#endif /* #ifdef PH_HAL4_ENABLE */ + return status; +} + +static NFCSTATUS phFriNfc_Desfire_HGetUIDDetails(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + if( ( NdefMap->SendRecvBuf[*(NdefMap->SendRecvLength)- 1] == PH_FRINFC_DESF_NATIVE_GETVER_RESP) ) + { + /*set the state*/ + NdefMap->State = PH_FRINFC_DESF_STATE_GET_UID; + + /* Helper routine to wrap the native desfire commands*/ + PH_FRINFC_DESF_ISO_NATIVE_WRAPPER(); + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + } +#ifdef PH_HAL4_ENABLE + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } +#endif /* #ifdef PH_HAL4_ENABLE */ + return status; + +} + +static NFCSTATUS phFriNfc_Desfire_HUpdateVersionDetails(const phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + if( ( NdefMap->SendRecvBuf[*(NdefMap->SendRecvLength)- 1] == 0xAF) ) + { + + status = NFCSTATUS_SUCCESS; + + /* We do not need the following details presently.Retained for future use*/ + #if 0 + NdefMap->AddInfo.Type4Info.MajorVersion = NdefSmtCrdFmt->SendRecvBuf[3]; + NdefMap->AddInfo.Type4Info.MinorVersion = NdefSmtCrdFmt->SendRecvBuf[4]; + if ( ( NdefMap->AddInfo.Type4Info.MajorVersion == 0x00 )&& + ( NdefMap->AddInfo.Type4Info.MinorVersion == 0x06 )) + { + /* card size of DESFire4 type */ + //NdefMap->AddInfo.Type4Info.CardSize = 0xEDE; + + } + else + { + // need to handle the Desfire8 type cards + // need to use get free memory + } + #endif + } + return status; +} + + +#endif /* #ifdef PH_HAL4_ENABLE */ + +/*! +* \brief Initiates Reading of NDEF information from the Desfire Card. +* +* The function initiates the reading of NDEF information from a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be +* done once the action has been triggered. +*/ + +NFCSTATUS phFriNfc_Desfire_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBufferSize = *PacketDataLength; + /* To return actual number of bytes read to the caller */ + NdefMap->NumOfBytesRead = PacketDataLength ; + *NdefMap->NumOfBytesRead = 0; + + /* store the offset in to map context*/ + NdefMap->Offset = Offset; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (*NdefMap->DataCount == NdefMap->DesfireCapContainer.NdefDataLen)) + { + /* No space on card for Reading : we have already + reached the end of file ! + Offset is set to Continue Operation */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + + /* reset the inter flag*/ + NdefMap->DesfireCapContainer.IsNlenPresentFlag = 0; + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = 0; + + /* Set the desfire read operation */ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_READ_OP; + + /* Save the packet data buffer address in the context */ + NdefMap->ApduBuffer = PacketData; + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + + /* Select smart tag operation. First step for the read operation. */ + status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + } + + return status; +} + +/*! +* \brief Initiates Writing of NDEF information to the Remote Device. +* +* The function initiates the writing of NDEF information to a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ + +NFCSTATUS phFriNfc_Desfire_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBufferSize = *PacketDataLength; + NdefMap->WrNdefPacketLength = PacketDataLength; + + /* Now, let's initialize *NdefMap->WrNdefPacketLength to zero. + In case we get an error, this will be correctly set to "no byte written". + In case there is no error, this will be updated later on, in the _process function. + */ + *NdefMap->WrNdefPacketLength = 0; + + /* we have write access. */ + if( *NdefMap->DataCount >= PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) + { + /* No space on card for writing : we have already + reached the end of file ! + Offset is set to Continue Operation */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + /* Adapt the nb of bytes that the user would like to write */ + + /*set the defire write operation*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_WRITE_OP; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + NdefMap->Offset = Offset; + + /*Store the packet data buffer*/ + NdefMap->ApduBuffer = PacketData; + + /* Select smart tag operation. First step for the write operation. */ + status = phFriNfc_Desfire_SelectSmartTag (NdefMap); + } + return status; +} + +/*! +* \brief Check whether a particular Remote Device is NDEF compliant. +* +* The function checks whether the peer device is NDEF compliant. +* +*/ + +NFCSTATUS phFriNfc_Desfire_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + +#ifdef PH_HAL4_ENABLE + + /*Set the desfire operation flag*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP; + + /*Call Select Smart tag Functinality*/ + status = phFriNfc_Desfire_SelectSmartTag(NdefMap); +#else + /* Need to get the version details of the card, to + identify the the desfire4card type */ + status = phFriNfc_Desfire_HGetHWVersion(NdefMap); +#endif + + return (status); +} + +static NFCSTATUS phFriNfc_Desf_HChkAndParseTLV(phFriNfc_NdefMap_t *NdefMap, uint8_t BuffIndex) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if((NdefMap->SendRecvBuf[BuffIndex] <= 0x03) || + (NdefMap->SendRecvBuf[BuffIndex] >= 0x06) ) + { + status = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + /* check for the type of TLV*/ + NdefMap->TLVFoundFlag = + ((NdefMap->SendRecvBuf[BuffIndex] == 0x04)? + PH_FRINFC_NDEFMAP_DESF_NDEF_CNTRL_TLV: + PH_FRINFC_NDEFMAP_DESF_PROP_CNTRL_TLV); + + status = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_SUCCESS); + } + return status; +} + +static NFCSTATUS phFriNfc_Desfire_HSetGet_NLEN(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + if ( PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP == NdefMap->DespOpFlag) + { + + /*Call Select Smart tag Functinality*/ + status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + } + else + { + + /* Get the Data Count and set it to NoOfBytesWritten + Update the NLEN using Transceive cmd*/ + + /*Form the packet for the update binary command*/ + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xD6; + + /* As we need to set the NLEN @ first 2 bytes of NDEF File*/ + /* set the p1/p2 offsets */ + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + + /* Set only two bytes as NLEN*/ + NdefMap->SendRecvBuf[4] = 0x02; + + /* update NLEN */ + NdefMap->SendRecvBuf[5] = (uint8_t)(*NdefMap->DataCount >> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[6] = (uint8_t)(*NdefMap->DataCount & (0x00ff)); + + NdefMap->SendLength = 0x07 ; + + /* Change the state to Write */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_END; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + } + return status; +} + +static void phFriNfc_Desfire_HProcReadData(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_PENDING; + uint32_t BufferSize = 0; + uint8_t BufIndex=0; + uint16_t SizeToCpy=0; + + /* Need to check the Actual Ndef Length before copying the data to buffer*/ + /* Only NDEF data should be copied , rest all the data should be ignored*/ + /* Ex : Ndef File Size 50 bytes , but only 5 bytes(NLEN) are relavent to NDEF data*/ + /* component should only copy 5 bytes to user buffer*/ + + /* Data has been read successfully in the TRX buffer. */ + /* copy it to the user buffer. */ + + /* while copying need check the offset if its begin need to skip the first 2 bytes + while copying. If its current no need to skip the first 2 bytes*/ + + if ( NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + BufIndex = (uint8_t)(( NdefMap->DesfireCapContainer.IsNlenPresentFlag == 1 )? + 0:PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES); + + /* Update the latest NLEN to context*/ + NdefMap->DesfireCapContainer.NdefDataLen = ((*NdefMap->DataCount == 0)? + ( (((uint16_t)NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_FIRST_INDEX])<<8)+ \ + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_SECOND_INDEX]): + NdefMap->DesfireCapContainer.NdefDataLen); + + /* Decide how many byes to be copied into user buffer: depending upon the actual NDEF + size need to copy the content*/ + if ( (NdefMap->DesfireCapContainer.NdefDataLen) <= (*NdefMap->SendRecvLength - \ + (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET + BufIndex))) + { + SizeToCpy = NdefMap->DesfireCapContainer.NdefDataLen; + + } + else + { + SizeToCpy = ((*NdefMap->SendRecvLength)-(PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET+BufIndex)); + } + + /* Check do we have Ndef Data len > 0 present in the card.If No Ndef Data + present in the card , set the card state to Initalised and set an Error*/ + if ( NdefMap->DesfireCapContainer.NdefDataLen == 0x00 ) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); +#ifdef PH_HAL4_ENABLE +#else + NdefMap->PrevOperation = 0; +#endif /* #ifdef PH_HAL4_ENABLE */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } + else + { + (void)memcpy( (&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[BufIndex])), + (SizeToCpy)); + + /* Increment the Number of Bytes Read, which will be returned to the caller. */ + *NdefMap->NumOfBytesRead +=SizeToCpy; + + /*update the data count*/ + *NdefMap->DataCount += SizeToCpy; + + /*update the buffer index of the apdu buffer*/ + NdefMap->ApduBuffIndex += SizeToCpy; + } + } + else + { + (void)memcpy( (&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex])), + (NdefMap->SendRecvBuf),/* to avoid the length of the NDEF File*/ + (*(NdefMap->SendRecvLength)-(PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET))); + + /* Increment the Number of Bytes Read, which will be returned to the caller. */ + *NdefMap->NumOfBytesRead +=( *NdefMap->SendRecvLength - \ + (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET)); + + /*update the data count*/ + *NdefMap->DataCount += \ + (*NdefMap->SendRecvLength - (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET)); + + /*update the buffer index of the apdu buffer*/ + NdefMap->ApduBuffIndex += \ + *NdefMap->SendRecvLength - (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET ); + } + + /* check whether we still have to read some more data. */ + if (*NdefMap->DataCount < NdefMap->DesfireCapContainer.NdefDataLen ) + { + /* we have some bytes to read. */ + + /* Now check, we still have bytes left in the user buffer. */ + BufferSize = NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex; + if(BufferSize != 0) + { + /* Before read need to set the flag to intimate the module to + dont skip the first 2 bytes as we are in mode reading next + continues available bytes, which will not contain the NLEN + information in the begining part that is 2 bytes*/ + NdefMap->DesfireCapContainer.IsNlenPresentFlag = 1; + /* Read Operation is not complete */ + Result = phFriNfc_Desfire_ReadBinary( NdefMap ); + /* handle the error in Transc function*/ + if ( (Result & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER) ) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } + } + else + { + /* There are some more bytes to read, but + no space in the user buffer */ + Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + NdefMap->ApduBuffIndex =0; + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } + } + else + { + if (*NdefMap->DataCount == NdefMap->DesfireCapContainer.NdefDataLen ) + { + /* we have read all the bytes available in the card. */ + Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); +#ifdef PH_HAL4_ENABLE + /* Do nothing */ +#else + NdefMap->PrevOperation = 0; +#endif /* #ifndef PH_HAL4_ENABLE */ + } + else + { + /* The control should not come here. */ + /* we have actually read more byte than available in the card. */ + NdefMap->PrevOperation = 0; +#ifndef PH_HAL4_ENABLE + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_CMD_ABORTED); +#else + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_FAILED); +#endif + } + + + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } +} + + + +/*! +* \brief Completion Routine, Processing function, needed to avoid long blocking. +* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion +* Routine in order to be able to notify the component that an I/O has finished and data are +* ready to be processed. +* +*/ + +void phFriNfc_Desfire_Process(void *Context, + NFCSTATUS Status) +{ + /*Set the context to Map Module*/ + phFriNfc_NdefMap_t *NdefMap = (phFriNfc_NdefMap_t *)Context; + uint8_t ErrFlag = 0; + uint16_t NLength = 0, + SendRecLen=0; + uint32_t BytesRead = 0; + + + /* Sujatha P: Fix for 0000255/0000257:[gk] MAP:Handling HAL Errors */ + if ( Status == NFCSTATUS_SUCCESS ) + { + switch (NdefMap->State) + { + +#ifdef PH_HAL4_ENABLE +#else + + case PH_FRINFC_DESF_STATE_GET_HW_VERSION : + + /* Check and store the h/w and s/w specific details. + Ex: Major/Minor version, memory storage info. */ + Status = phFriNfc_Desfire_HGetSWVersion(NdefMap); + + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + + break; + + case PH_FRINFC_DESF_STATE_GET_SW_VERSION : + + /* Check and store the h/w and s/w specific details. + Ex: Major/Minor version, memory storage info. */ + + Status = phFriNfc_Desfire_HUpdateVersionDetails(NdefMap); + if ( Status == NFCSTATUS_SUCCESS ) + { + Status = phFriNfc_Desfire_HGetUIDDetails(NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + + break; + + case PH_FRINFC_DESF_STATE_GET_UID : + + /*Set the desfire operation flag*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP; + + /*Call Select Smart tag Functinality*/ + Status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + + break; +#endif /* #ifdef PH_HAL4_ENABLE */ + + case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG: + + if(( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + Status = phFriNfc_Desfire_SelectFile(NdefMap); + + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /*Error " Smart Tag Functionality Not Supported"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED); + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + + } + + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_FILE : + + if(( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /*check for the which operation */ + if( (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_READ_OP) || + (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP) || + (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP )) + { + /* call for read binary operation*/ + Status = phFriNfc_Desfire_ReadBinary(NdefMap); + + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER) ) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + /*its a write Operation*/ + else if(NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_WRITE_OP ) + { + Status = phFriNfc_Desfire_UpdateBinary (NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /* unknown/invalid desfire operations*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /*return Error " Select File Operation Failed"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_READ_CAP_CONT: + if( (NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength)-2)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength)-1)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /* Read successful. */ + /*Update the smart tag capability container*/ + Status = phFriNfc_Desfire_Update_SmartTagCapContainer(NdefMap); + + if ( Status == NFCSTATUS_SUCCESS) + { + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP; + Status = phFriNfc_Desfire_HSetGet_NLEN(NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + + } + + } + else + { + /*return Error " Capability Container Not Found"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_READ_BIN: + + /* Check how many bytes have been read/returned from the card*/ + BytesRead = phFriNfc_Desfire_HGetLeBytes(NdefMap); + + /* set the send recev len*/ + SendRecLen = *NdefMap->SendRecvLength - (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET ); + if ( (NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1) && ((BytesRead == 1) || (BytesRead == 2 ))) + { + BytesRead += PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; /* to take care of first 2 len bytes*/ + + } + else + { + /* Nothing to process*/ + ; + } + /* Read More Number Of Bytes than Expected*/ + if ( ( BytesRead == SendRecLen ) && + ((NdefMap->SendRecvBuf[(*NdefMap->SendRecvLength-2)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[(*NdefMap->SendRecvLength-1)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE))) + + { + /* this is to check the card state in first Read Operation*/ + if ( NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP ) + { + /* check the actual length of the ndef data : NLEN*/ + NLength = ( (((uint16_t)NdefMap->SendRecvBuf[0])<<PH_FRINFC_NDEFMAP_DESF_SHL8)+ \ + NdefMap->SendRecvBuf[1]); + if (( NLength > PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE )|| + ( NLength == 0xFFFF)) + { + ErrFlag = 1; + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + /* Store the NLEN into the context */ + NdefMap->DesfireCapContainer.NdefDataLen = NLength; + + Status = phFriNfc_MapTool_SetCardState( NdefMap, + NLength); + if ( Status == NFCSTATUS_SUCCESS ) + { + /*Set the card type to Desfire*/ + NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; + /*Set the state to specify True for Ndef Compliant*/ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_CHK_NDEF; + /*set the data count back to zero*/; + *NdefMap->DataCount = 0; + /*set the apdu buffer index to zero*/ + NdefMap->ApduBuffIndex = 0; + /* Set the Operationg flag to Complete check NDEF Operation*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP; + + } + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + }/* End ofNdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP*/ + } + else if ( NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_READ_OP ) + { + phFriNfc_Desfire_HProcReadData(NdefMap); + } + else + { + /* Invalid Desfire Operation */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_READ_FAILED); + ErrFlag =1; + } + if( ErrFlag == 1) + { + *NdefMap->DataCount = 0; + + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_BEGIN: + if( (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /* Write operation was successful. */ + /* NdefMap->NumOfBytesWritten have been written on to the card. + Update the DataCount and the ApduBufferIndex */ + *NdefMap->DataCount += NdefMap->NumOfBytesWritten; + NdefMap->ApduBuffIndex += NdefMap->NumOfBytesWritten; + + /* Update the user-provided buffer size to write */ + *NdefMap->WrNdefPacketLength += NdefMap->NumOfBytesWritten; + + /* Call Upadte Binary function to check if some more bytes are to be written. */ + Status = phFriNfc_Desfire_UpdateBinary( NdefMap ); + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + break; + case PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_END : + if((NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /* Updating NLEN operation was successful. */ + /* Entire Write Operation is complete*/ + /* Reset the relevant parameters. */ + Status = PHNFCSTVAL(CID_NFC_NONE,\ + NFCSTATUS_SUCCESS); + + /* set the state & Data len into context*/ + NdefMap->CardState = ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INITIALIZED)? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState); + + NdefMap->DesfireCapContainer.NdefDataLen = (uint16_t)(*NdefMap->WrNdefPacketLength); +#ifdef PH_HAL4_ENABLE + /* Do nothing */ +#else + NdefMap->PrevOperation = 0; +#endif /* #ifndef PH_HAL4_ENABLE */ + + } + else + { + NdefMap->PrevOperation = 0; + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + } + + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + break; + + default: + /*define the invalid state*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_DEVICE_REQUEST); + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + break; + } + } + else + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } +} + + + +/*! +* \brief this shall select the smart tag functinality of the Desfire card. +* +* Only when this command returns command completed it is a Smart Tag +* compatible product. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_SelectSmartTag(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + /*form the packet for Select smart tag command*/ + NdefMap->SendRecvBuf[0] = 0x00; /* cls */ + NdefMap->SendRecvBuf[1] = 0xa4; /* ins */ + NdefMap->SendRecvBuf[2] = 0x04; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[4] = 0x07; /* lc */ + + /* next 7 bytes specify the DF Name*/ + NdefMap->SendRecvBuf[5] = 0xd2; + NdefMap->SendRecvBuf[6] = 0x76; + NdefMap->SendRecvBuf[7] = 0x00; + NdefMap->SendRecvBuf[8] = 0x00; + NdefMap->SendRecvBuf[9] = 0x85; + NdefMap->SendRecvBuf[10] = 0x01; + NdefMap->SendRecvBuf[11] = 0x00; + + /*Set the Send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_SMARTTAG_PKT_SIZE; + + /* Change the state to Select Smart Tag */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + + return status; +} + +/*! +* \brief this shall select/access the capability container of the Desfire +* card. +* +* This shall be used to identify, if NDEF data structure do exist on +* the smart tag, we receive command completed status. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_SelectFile (phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + /* check for the invalid/unknown desfire operations*/ + if ((NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP)&& \ + (NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_READ_OP)&&\ + ( NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_WRITE_OP) && + ( NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP)) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + + /* Set the command*/ + //NdefMap->Cmd.Iso144434Cmd = phHal_eIso14443_4_CmdListTClCmd; + + /* Form the packet for select file command either for the + Check Ndef/Read/Write functionalities*/ + NdefMap->SendRecvBuf[0] = 0x00; /* cls */ + NdefMap->SendRecvBuf[1] = 0xa4; /* ins */ + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[4] = 0x02; /* lc */ + + if ( (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP)) + + { + /* cap container file identifier*/ + NdefMap->SendRecvBuf[5] = 0xe1; + NdefMap->SendRecvBuf[6] = 0x03; + } + /* Mantis entry 0394 fixed */ + else + { + NdefMap->SendRecvBuf[5] = (uint8_t)((NdefMap->DesfireCapContainer.NdefMsgFid) >> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[6] = (uint8_t)((NdefMap->DesfireCapContainer.NdefMsgFid) & (0x00ff)); + } + /*Set the Send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_SELECT_FILE_PKT_SIZE; + + /* Change the state to Select File */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_FILE; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + + } + + return status; + +} + +/*! +* \brief this shall read the data from Desfire card. +* +* This is used in two cases namely Reading the Capability container +* data( le == 0 ) and reading the file data.Maximum bytes to be read during +* a single read binary is known after the reading the data from the capability +* conatainer. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_ReadBinary(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint32_t BytesToRead = 0; + uint8_t BufIndex=0,OperFlag=0; + uint16_t DataCnt=0; + + /* to read the capability container data*/ + if (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP ) + { + /*specifies capability container shall be read*/ + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xb0; + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[4] = 0x0F; /* le */ + + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_READ_BIN_PKT_SIZE; + + /* Change the state to Cap Container Read */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_READ_CAP_CONT; + + /* set the send receive buffer length*/ + OperFlag = 1; + } + /*desfire file read operation*/ + else + { + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xb0; + + /*TBD the NLEN bytes*/ + if( *NdefMap->DataCount == 0 ) + { + /* first read */ + /* set the offset p1 and p2*/ + NdefMap->SendRecvBuf[2] = 0; + NdefMap->SendRecvBuf[3] = 0; + } + else + { + /* as the p1 of the 8bit is 0, p1 and p2 are used to store the + ofset value*/ + DataCnt = *NdefMap->DataCount; + DataCnt += PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + NdefMap->SendRecvBuf[2] = (uint8_t)((DataCnt)>> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[3] = (uint8_t)((DataCnt)& (0x00ff)); + } + /* calculate the Le Byte*/ + BytesToRead = phFriNfc_Desfire_HGetLeBytes(NdefMap); + + if ( NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + /* BufIndex represents the 2 NLEN bytes and decides about the presence of + 2 bytes NLEN data*/ + + BufIndex = (uint8_t)(( NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1 ) ? + PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES:0); + + if( ((BytesToRead == 1) || (BytesToRead == 2)) && (NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1)) + { + BytesToRead += BufIndex; + } + } + + /* set the Le byte*/ + /* This following code is true for get nlen and current offset set*/ + NdefMap->SendRecvBuf[4]=(uint8_t) BytesToRead ; + + /* Change the state to Read */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_READ_BIN; + + /*set the send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_READ_BIN_PKT_SIZE; + OperFlag = 2; + } + + if (OperFlag == 1 ) + { + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + } + else + { + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,(uint8_t)(BytesToRead +PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET)); + } + return (status); +} + +/*! +* \brief this shall write the data to Desfire card. +* Maximum bytes to be written during a single update binary +* is known after the reading the data from the capability +* conatainer. +* +* le filed specifes , how many bytes of data to be written to the +* Card. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_UpdateBinary(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + uint16_t noOfBytesToWrite = 0, DataCnt=0, + index=0; + + /* Do we have space in the file to write? */ + if ( (*NdefMap->DataCount < PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) && + (NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize)) + { + /* Yes, we have some bytes to write */ + /* Check and set the card memory size , if user sent bytes are more than the + card memory size*/ + if( (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >\ + (uint16_t)(PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE - *NdefMap->DataCount)) + { + NdefMap->ApduBufferSize =( (PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) - (*NdefMap->DataCount + NdefMap->ApduBuffIndex)); + } + + /* Now, we have space in the card to write the data, */ + /*Form the packet for the update binary command*/ + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xD6; + + if( *NdefMap->DataCount == 0) + { + /* set the p1/p2 offsets */ + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = 0; + } + else + { + /* as the p1 of the 8bit is 0, p1 and p2 are used to store the + ofset value*/ + /* This sets card offset in a card for a write operation. + 2 is + added as first 2 offsets represents the size of the NDEF Len present + in the file*/ + + DataCnt = *NdefMap->DataCount; + DataCnt += PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + NdefMap->SendRecvBuf[2] = (uint8_t)((DataCnt)>> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[3] = (uint8_t)((DataCnt)& (0x00ff)); + /* No need to attach 2 NLEN bytes at the begining. + as we have already attached in the first write operation.*/ + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = 1; + + } + + /* Calculate the bytes to write */ + if( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)( NdefMap->DesfireCapContainer.MaxCmdSize )) + + { + noOfBytesToWrite = ( ( NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1) ? + NdefMap->DesfireCapContainer.MaxCmdSize : + (NdefMap->DesfireCapContainer.MaxCmdSize - PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES)); + } + else + { + /* Read only till the available buffer space */ + noOfBytesToWrite = (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + } + + if ( NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + if ( NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1 ) + { + index = 5; + /* To Specify the NDEF data len written : updated at the of write cycle*/ + NdefMap->SendRecvBuf[4] = (uint8_t)noOfBytesToWrite; + } + else + { + /* Leave space to update NLEN */ + NdefMap->SendRecvBuf[5] = 0x00; + NdefMap->SendRecvBuf[6] = 0x00; + index =7; + /* To Specify the NDEF data len written : updated at the of write cycle*/ + NdefMap->SendRecvBuf[4] = (uint8_t)noOfBytesToWrite + PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + } + + /* copy the data to SendRecvBuf from the apdu buffer*/ + (void)memcpy( &NdefMap->SendRecvBuf[index], + &NdefMap->ApduBuffer[NdefMap->ApduBuffIndex], + noOfBytesToWrite); + NdefMap->SendLength = (noOfBytesToWrite + index); + } + else + { + NdefMap->SendRecvBuf[4] = (uint8_t)noOfBytesToWrite; + + /* copy the data to SendRecvBuf from the apdu buffer*/ + (void)memcpy( &NdefMap->SendRecvBuf[5], + &NdefMap->ApduBuffer[NdefMap->ApduBuffIndex], + noOfBytesToWrite); + NdefMap->SendLength = (noOfBytesToWrite + 5); + } + + /* Store the number of bytes being written in the context structure, so that + the parameters can be updated, after a successful write operation. */ + NdefMap->NumOfBytesWritten = noOfBytesToWrite; + + /* Change the state to Write */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_BEGIN; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + + } /* if(NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize) */ + else + { + if ( (*NdefMap->DataCount == PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) || + (NdefMap->ApduBuffIndex == NdefMap->ApduBufferSize)) + { + /* The NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_SET_LEN_OP is not + required, because the DespOpFlag shall be WRITE_OP + */ + /* Update the NLEN Bytes*/ +#ifdef PH_HAL4_ENABLE + /* Do nothing */ +#else + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_SET_LEN_OP; +#endif /* #ifdef PH_HAL4_ENABLE */ + status = phFriNfc_Desfire_HSetGet_NLEN(NdefMap); + } + else + { + /* The control should not come here. + wrong internal calculation. + we have actually written more than the space available + in the card ! */ +#ifndef PH_HAL4_ENABLE + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_CMD_ABORTED); +#else + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_FAILED); +#endif + /* Reset the relevant parameters. */ + NdefMap->ApduBuffIndex = 0; + NdefMap->PrevOperation = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,status); + } + + } + /* if(*NdefMap->DataCount < PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) */ + + return status; +} + + +static void phFriNfc_Desfire_HChkNDEFFileAccessRights(phFriNfc_NdefMap_t *NdefMap) +{ + if ( (NdefMap->DesfireCapContainer.ReadAccess == 0x00) && + (NdefMap->DesfireCapContainer.WriteAccess == 0x00 )) + { + /* Set the card state to Read/write State*/ + /* This state can be either INITIALISED or READWRITE. but default + is INITIALISED */ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + + } + else if((NdefMap->DesfireCapContainer.ReadAccess == 0x00) && + (NdefMap->DesfireCapContainer.WriteAccess == 0xFF )) + { + /* Set the card state to Read Only State*/ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } + else + { + /* Set the card state to invalid State*/ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } +} + +/*! +* \brief this shall update the Desfire capability container structure. +* +* This function shall store version,maximum Ndef data structure size, +* Read Access permissions, Write Access permissions , Maximum data size +* that can be sent using a single Update Binary, maximum data size that +* can be read from the Desfire using a singlr read binary. +* These vaues shall be stored and used during the read/update binary +* operations. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_Update_SmartTagCapContainer(phFriNfc_NdefMap_t *NdefMap) +{ + uint16_t CapContSize = 0, + /* this is initalised 2 because CCLEN includes the field size bytes i.e 2bytes*/ + CCLen= 0; + uint8_t ErrFlag = 0; + + NFCSTATUS status= NFCSTATUS_SUCCESS; + + /*Check the Size of Cap Container */ + CapContSize = ( (((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_FIRST_INDEX])<<8)+ \ + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_SECOND_INDEX]); + + CCLen += 2; + + if ( (CapContSize < 0x0f) || (CapContSize == 0xffff)) + { + ErrFlag =1; + } + else + { + /*Version : Smart Tag Spec version */ + /* check for the validity of Major and Minor Version numbers*/ + status = phFriNfc_MapTool_ChkSpcVer ( NdefMap, + PH_FRINFC_NDEFMAP_DESF_VER_INDEX); + if ( status != NFCSTATUS_SUCCESS ) + { + ErrFlag =1; + } + else + { + CCLen += 1; + + /*Get Response APDU data size + to check the integration s/w response size*/ +#ifdef PH_HAL4_ENABLE + { + uint16_t max_rsp_size = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_FIRST_INDEX]) << 8)\ + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_SECOND_INDEX]); + NdefMap->DesfireCapContainer.MaxRespSize = + ((max_rsp_size > PHHAL_MAX_DATASIZE)? + (PHHAL_MAX_DATASIZE) : max_rsp_size); + } +#else + NdefMap->DesfireCapContainer.MaxRespSize = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_FIRST_INDEX]) << 8)\ + +NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_SECOND_INDEX]); +#endif /* #ifdef PH_HAL4_ENABLE */ + + /*Get Command APDU data size*/ +#ifdef PH_HAL4_ENABLE + { + uint16_t max_cmd_size = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_FIRST_INDEX])<<8)\ + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_SECOND_INDEX]); + + NdefMap->DesfireCapContainer.MaxCmdSize = + ((max_cmd_size > PHHAL_MAX_DATASIZE)? + (PHHAL_MAX_DATASIZE): max_cmd_size); + } +#else + NdefMap->DesfireCapContainer.MaxCmdSize = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_FIRST_INDEX])<<8)\ + +NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_SECOND_INDEX]); +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Check for the Validity of Cmd & Resp Size*/ + /* check the Validity of the Cmd Size*/ + if( (NdefMap->DesfireCapContainer.MaxRespSize < 0x0f) || + ( NdefMap->DesfireCapContainer.MaxCmdSize == 0x00)) + { + ErrFlag=1; + + } + else + { + CCLen += 4; + + /* Check and Parse the TLV structure */ + /* In future this chk can be extended to Propritery TLV */ + //status = phFriNfc_ChkAndParseTLV(NdefMap); + status = phFriNfc_Desf_HChkAndParseTLV(NdefMap,PH_FRINFC_NDEFMAP_DESF_TLV_INDEX); + if ( (status == NFCSTATUS_SUCCESS) && (NdefMap->TLVFoundFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CNTRL_TLV)) + { + CCLen += 1; + + /* check the TLV length*/ + if ( (( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX]) > 0x00 ) && + (( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX]) <= 0xFE )&& + (( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX]) == 0x06 )) + { + CCLen +=1; + /* store the contents in to the container structure*/ + NdefMap->DesfireCapContainer.NdefMsgFid = ( (((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILEID_BYTE_FIRST_INDEX])<<PH_FRINFC_NDEFMAP_DESF_SHL8)+ \ + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILEID_BYTE_SECOND_INDEX]); + + CCLen +=2; + + /* Invalid Msg File Id : User Can't Have read/write Opeartion*/ + if ( (NdefMap->DesfireCapContainer.NdefMsgFid == 0xFFFF) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0xE102) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0xE103) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0x3F00) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0x3FFF ) ) + { + + ErrFlag=1; + } + else + { + /*Get Ndef Size*/ + NdefMap->DesfireCapContainer.NdefFileSize = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILESZ_BYTE_FIRST_INDEX])<<8) + | (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILESZ_BYTE_SECOND_INDEX] & 0x00ff)); + + + /*Check Ndef Size*/ + /* TBD : Do we need to minus 2 bytes of size it self?*/ + if ( ((NdefMap->DesfireCapContainer.NdefFileSize -2) <= 0x0004 ) || + ((NdefMap->DesfireCapContainer.NdefFileSize -2) == 0xFFFD ) ) + { + ErrFlag=1; + } + else + { + CCLen +=2; + + /*Ndef File Read Access*/ + NdefMap->DesfireCapContainer.ReadAccess = NdefMap->\ + SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILERD_ACCESS_INDEX] ; + + /*Ndef File Write Access*/ + NdefMap->DesfireCapContainer.WriteAccess = NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILEWR_ACCESS_INDEX]; + + CCLen +=2; + + phFriNfc_Desfire_HChkNDEFFileAccessRights(NdefMap); + } + } + } + else + { + + /* TLV Lenth is of two byte value + TBD: As the length of TLV is fixed for 6 bytes. We need not + handle the 2 byte value*/ + + + } + } + else + { + if ( NdefMap->TLVFoundFlag == PH_FRINFC_NDEFMAP_DESF_PROP_CNTRL_TLV ) + { + /*TBD: To Handle The Proprietery TLV*/ + } + else + { + /*Invalid T found case*/ + ErrFlag =1; + } + } + /* check for the entire LENGTH Validity + CCLEN + TLV L value == CCLEN*/ + if ( CapContSize != CCLen ) + { + ErrFlag=1; + } + + }/* if NdefMap->DesfireCapContainer.MaxRespSize < 0x0f */ + }/* Chkeck Map Version*/ + }/* CC size invalid*/ + if( ErrFlag == 1 ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + return ( status ); +} + +static uint32_t phFriNfc_Desfire_HGetLeBytes(phFriNfc_NdefMap_t *NdefMap) +{ + /*Represents the LE byte*/ + uint16_t BytesToRead =0; + + if ( NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP ) + { + BytesToRead = PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + NdefMap->DesfireCapContainer.SkipNlenBytesFlag =0; + } + else + { + + /* Calculate Le bytes : No of bytes to read*/ + /* Check for User Apdu Buffer Size and Msg Size of Desfire Capability container */ + if((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= NdefMap->DesfireCapContainer.MaxRespSize) + { + /* We have enough buffer space to read the whole capability container + size bytes + Now, check do we have NdefMap->DesfireCapContainer.MaxRespSize to read ? */ + + BytesToRead = (((NdefMap->DesfireCapContainer.NdefDataLen - *NdefMap->DataCount) >= + NdefMap->DesfireCapContainer.MaxRespSize) ? + NdefMap->DesfireCapContainer.MaxRespSize : + (NdefMap->DesfireCapContainer.NdefDataLen - + *NdefMap->DataCount)); + } + else + { + /* Read only till the available buffer space */ + BytesToRead = (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + if(BytesToRead >= (uint16_t)(NdefMap->DesfireCapContainer.NdefDataLen - *NdefMap->DataCount)) + { + BytesToRead = (NdefMap->DesfireCapContainer.NdefDataLen - *NdefMap->DataCount); + } + } + + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = + (uint8_t)(((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN )&&( *NdefMap->DataCount == 0 )) ? + 1 : 0); + + } + return (BytesToRead); +} + + + +/*! +* \brief this shall notify the integration software with respective +* success/error status along with the completion routines. +* +* This routine is called from the desfire process function. +* +*/ + +static void phFriNfc_Desfire_HCrHandler( phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + switch(NdefMap->DespOpFlag) + { + /* check which routine has the problem and set the CR*/ + case PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_CHK_NDEF].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + case PH_FRINFC_NDEFMAP_DESF_READ_OP : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_RD_NDEF].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + case PH_FRINFC_NDEFMAP_DESF_WRITE_OP : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_WR_NDEF].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + default : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_INVALID_OPE].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + } +} + +static NFCSTATUS phFriNfc_Desfire_HSendTransCmd(phFriNfc_NdefMap_t *NdefMap,uint8_t SendRecvLen) +{ + + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* set the command type*/ +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.Iso144434Cmd = phHal_eIso14443_4_CmdListTClCmd; +#else + NdefMap->Cmd.Iso144434Cmd = phHal_eIso14443_4_Raw; +#endif + + /* set the Additional Info*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /*set the completion routines for the desfire card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_Desfire_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /* set the receive length */ + *NdefMap->SendRecvLength = ((uint16_t)(SendRecvLen)); + + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return (status); + + +} + + +#ifdef UNIT_TEST +#include <phUnitTestNfc_Desfire_static.c> +#endif + +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ |