| /* |
| * 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: Tue Jul 27 08:58:22 2010 $ |
| * $Author: ing02260 $ |
| * $Revision: 1.11 $ |
| * $Aliases: $ |
| * |
| */ |
| |
| #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.11 $" |
| #define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: $" |
| |
| /*@}*/ |
| |
| /***************** Start of MACROS ********************/ |
| #ifdef DESFIRE_EV1 |
| #define DESFIRE_EV1_P2_OFFSET_VALUE (0x0CU) |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| /***************** End of MACROS ********************/ |
| |
| /*@}*/ |
| |
| /*! |
| * \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; |
| |
| #ifdef DESFIRE_EV1 |
| /* Select smart tag operation. First step for the read operation. */ |
| if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) |
| { |
| status = phFriNfc_Desfire_SelectFile(NdefMap); |
| } |
| else |
| #endif /* #ifdef DESFIRE_EV1 */ |
| { |
| 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; |
| |
| #ifdef DESFIRE_EV1 |
| if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) |
| { |
| status = phFriNfc_Desfire_SelectFile(NdefMap); |
| } |
| else |
| #endif /* #ifdef DESFIRE_EV1 */ |
| { |
| /* 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 |
| |
| #ifdef DESFIRE_EV1 |
| /* Reset card type */ |
| NdefMap->CardType = 0; |
| #endif /* #ifdef DESFIRE_EV1 */ |
| /*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 = (uint32_t)(*NdefMap->NumOfBytesRead + SizeToCpy); |
| |
| /*update the data count*/ |
| *NdefMap->DataCount = (uint16_t)(*NdefMap->DataCount + SizeToCpy); |
| |
| /*update the buffer index of the apdu buffer*/ |
| NdefMap->ApduBuffIndex = (uint16_t)(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 */ |
| |
| #ifdef DESFIRE_EV1 |
| case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1: |
| { |
| 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)) |
| { |
| NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; |
| |
| 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 |
| { |
| NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; |
| /* The card is not the new desfire, so send select smart tag command |
| of the old desfire */ |
| Status = phFriNfc_Desfire_SelectSmartTag(NdefMap); |
| |
| |
| } |
| break; |
| } |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG: |
| #ifdef DESFIRE_EV1 |
| 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)) |
| #else |
| 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)) |
| #endif /* #ifdef DESFIRE_EV1 */ |
| { |
| 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); |
| #ifdef DESFIRE_EV1 |
| NdefMap->CardType = 0; |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| /* 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; |
| #ifdef DESFIRE_EV1 |
| if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) |
| { |
| Status = phFriNfc_Desfire_SelectFile(NdefMap); |
| } |
| else |
| #endif /* #ifdef DESFIRE_EV1 */ |
| { |
| 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*/ |
| #ifndef DESFIRE_EV1 |
| NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; |
| #endif /* #ifdef DESFIRE_EV1 */ |
| /*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 = (uint16_t)(*NdefMap->DataCount + |
| NdefMap->NumOfBytesWritten); |
| NdefMap->ApduBuffIndex = (uint16_t)(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 = (uint8_t)((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; |
| #ifdef DESFIRE_EV1 |
| uint8_t card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| /*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; |
| |
| #ifdef DESFIRE_EV1 |
| |
| switch (NdefMap->DespOpFlag) |
| { |
| case PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP: |
| { |
| /* First select the smart tag using the new desfire EV1 and increment the |
| "sel_index" and if it fails then try the old desfire select smart tag |
| command */ |
| if (0 == NdefMap->CardType) |
| { |
| /* p2 |
| NdefMap->SendRecvBuf[3] = DESFIRE_EV1_P2_OFFSET_VALUE; */ |
| NdefMap->SendRecvBuf[11] = 0x01; |
| /* Le */ |
| NdefMap->SendRecvBuf[12] = 0x00; |
| NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1; |
| card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; |
| } |
| else |
| { |
| NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ |
| NdefMap->SendRecvBuf[11] = 0x00; |
| NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; |
| card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; |
| } |
| break; |
| } |
| |
| case PH_FRINFC_NDEFMAP_DESF_READ_OP: |
| default : |
| { |
| if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) |
| { |
| NdefMap->SendRecvBuf[11] = 0x01; |
| NdefMap->SendRecvBuf[12] = 0x00; |
| NdefMap->State = (uint8_t)PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1; |
| card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; |
| } |
| else |
| { |
| NdefMap->SendRecvBuf[11] = 0x00; |
| NdefMap->State = (uint8_t)PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; |
| card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; |
| } |
| break; |
| } |
| } |
| |
| #else /* #ifdef DESFIRE_EV1 */ |
| |
| NdefMap->SendRecvBuf[11] = 0x00; |
| |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| /*Set the Send length*/ |
| NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_SMARTTAG_PKT_SIZE; |
| #ifdef DESFIRE_EV1 |
| |
| if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == card_type) |
| { |
| /* Send length is updated for the NEW DESFIRE EV1 */ |
| NdefMap->SendLength = (uint16_t)(NdefMap->SendLength + 1); |
| } |
| |
| #else |
| /* Change the state to Select Smart Tag */ |
| NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| 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 */ |
| |
| #ifdef DESFIRE_EV1 |
| if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) |
| { |
| NdefMap->SendRecvBuf[3] = DESFIRE_EV1_P2_OFFSET_VALUE; /* p2 */ |
| } |
| #endif /* #ifdef DESFIRE_EV1 */ |
| |
| 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 */ |