C++程序  |  432行  |  15.43 KB

/*
 * Copyright (C) 2010 NXP Semiconductors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * \file  phFriNfc_MifULFormat.c
 * \brief NFC Ndef Formatting For Mifare ultralight card.
 *
 * Project: NFC-FRI
 *
 * $Date: Fri Oct 23 12:00:05 2009 $
 * $Author: ing02260 $
 * $Revision: 1.8 $
 * $Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
 *
 */

#include <phFriNfc_MifULFormat.h>
#include <phFriNfc_OvrHal.h>

/*! \ingroup grp_file_attributes
 *  \name NDEF Mapping
 *
 * File: \ref phFriNfc_MifULFormat.c
 *
 */
/*@{*/
#define PHFRINFCMIFULFORMAT_FILEREVISION "$Revision: 1.8 $"
#define PHFRINFCMIFULFORMAT_FILEALIASES  "$Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $"
/*@}*/
/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the   
* transceive function
*/
static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt);

/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the   
* read or write operation
*/
static NFCSTATUS phFriNfc_MfUL_H_WrRd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);

/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function fills the  
* send buffer for transceive function
*/
static void phFriNfc_MfUL_H_fillSendBuf(phFriNfc_sNdefSmtCrdFmt_t   *NdefSmtCrdFmt,
                                        uint8_t                     BlockNo);

/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process
* the read bytes
*/
static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);

/*!
* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process the
* OTP bytes written
*/
static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt);

static int MemCompare1 ( void *s1, void *s2, unsigned int n );
/*The function does a comparision of two strings and returns a non zero value 
if two strings are unequal*/
static int MemCompare1 ( void *s1, void *s2, unsigned int n )
{
    int8_t   diff = 0;
    int8_t *char_1  =(int8_t *)s1;
    int8_t *char_2  =(int8_t *)s2;
    if(NULL == s1 || NULL == s2)
    {
        PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare");
    }
    else
    {
        for(;((n>0)&&(diff==0));n--,char_1++,char_2++)
        {
            diff = *char_1 - *char_2;
        }
    }
    return (int)diff;
}

void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES; 

    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
    (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                OTPByte,
                sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
}

NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    NFCSTATUS               Result = NFCSTATUS_SUCCESS;
    uint8_t                 OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
    
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
    (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                OTPByte,
                sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));

    /* Set the state */
    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RD_16BYTES;
    /* Initialise current block to the lock bits block */
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_2;
    
    /* Start authentication */
    Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
    return Result;
}

void phFriNfc_MfUL_Process(void             *Context,
                           NFCSTATUS        Status)
{
    phFriNfc_sNdefSmtCrdFmt_t  *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
    
    if(Status == NFCSTATUS_SUCCESS)
    {
        switch(NdefSmtCrdFmt->State)
        {
        case PH_FRINFC_MFUL_FMT_RD_16BYTES:
            Status = phFriNfc_MfUL_H_ProRd16Bytes(NdefSmtCrdFmt);
            break;

        case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
            Status = phFriNfc_MfUL_H_ProWrOTPBytes(NdefSmtCrdFmt);
            break;

        case PH_FRINFC_MFUL_FMT_WR_TLV:
#ifdef PH_NDEF_MIFARE_ULC               
            if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
            {
                /* Write NDEF TLV in block number 5 */
                NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 
                                                        PH_FRINFC_MFUL_FMT_VAL_5;
                /* Card already have the OTP bytes so write TLV */
                NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV1;
                
                Status = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
            }
#endif /* #ifdef PH_NDEF_MIFARE_ULC */

            break;

#ifdef PH_NDEF_MIFARE_ULC   
        case PH_FRINFC_MFUL_FMT_WR_TLV1:
        
        break;
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
        
        default:
            Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                NFCSTATUS_INVALID_DEVICE_REQUEST);
            break;
        }
    }
    /* Status is not success then call completion routine */
    if(Status != NFCSTATUS_PENDING)
    {
        phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status);
    }
}

static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
    NFCSTATUS   Result = NFCSTATUS_SUCCESS;

    /* Fill the send buffer */
    phFriNfc_MfUL_H_fillSendBuf(NdefSmtCrdFmt, 
                            NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock);

    /* Call transceive */
    Result = phFriNfc_MfUL_H_Transceive(NdefSmtCrdFmt);
    
    return Result;
}

static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
{
    NFCSTATUS   Result = NFCSTATUS_SUCCESS;

    /* set the data for additional data exchange*/
    NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
    NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
    NdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0;

    /*set the completion routines for the card operations*/
    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process;
    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt;

    *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;

    /* Call the Overlapped HAL Transceive function */ 
    Result = phFriNfc_OvrHal_Transceive(    NdefSmtCrdFmt->LowerDevice,
                                            &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
                                            NdefSmtCrdFmt->psRemoteDevInfo,
                                            NdefSmtCrdFmt->Cmd,
                                            &NdefSmtCrdFmt->psDepAdditionalInfo,
                                            NdefSmtCrdFmt->SendRecvBuf,
                                            NdefSmtCrdFmt->SendLength,
                                            NdefSmtCrdFmt->SendRecvBuf,
                                            NdefSmtCrdFmt->SendRecvLength);
    return Result;
}

static void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
                                 uint8_t                    BlockNo)
{
#ifdef PH_NDEF_MIFARE_ULC
    uint8_t     NDEFTLV1[4] = {0x01, 0x03, 0xA0, 0x10}; 
    uint8_t     NDEFTLV2[4] = {0x44, 0x03, 0x00, 0xFE}; 
#endif /* #ifdef PH_NDEF_MIFARE_ULC */
    uint8_t     NDEFTLV[4] = {0x03, 0x00, 0xFE, 0x00};


    
    
    /* First byte for send buffer is always the block number */
    NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_0] = (uint8_t)BlockNo;
    switch(NdefSmtCrdFmt->State)
    {
    case PH_FRINFC_MFUL_FMT_RD_16BYTES:
#ifdef PH_HAL4_ENABLE
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
#else
        /* Read command */
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
#endif /* #ifdef PH_HAL4_ENABLE */
        /* Send length for read command is always one */
        NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
        break;

    case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
        /* Send length for read command is always Five */
        NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
        /* Write command */
#ifdef PH_HAL4_ENABLE
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
#else
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
#endif /* #ifdef PH_HAL4_ENABLE */
        /* Copy the OTP bytes */
        (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], 
                    NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                    PH_FRINFC_MFUL_FMT_VAL_4);
        break;

    case PH_FRINFC_MFUL_FMT_WR_TLV:
#ifndef PH_NDEF_MIFARE_ULC      
    default:
#endif /* #ifndef PH_NDEF_MIFARE_ULC */    
        /* Send length for read command is always Five */
        NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
        /* Write command */
#ifdef PH_HAL4_ENABLE
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
#else
        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
#endif /* #ifdef PH_HAL4_ENABLE */        
        /* Copy the NDEF TLV */
#ifdef PH_NDEF_MIFARE_ULC

        if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
        {
            (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], 
                    NDEFTLV1,
                    PH_FRINFC_MFUL_FMT_VAL_4);
        }
        else if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD)
        {
            (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], 
                NDEFTLV,
                PH_FRINFC_MFUL_FMT_VAL_4);
        }
        else
        {
        }
#else
        (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], 
                    NDEFTLV,
                    PH_FRINFC_MFUL_FMT_VAL_4);

#endif /* #ifdef PH_NDEF_MIFARE_ULC */

        break;

#ifdef PH_NDEF_MIFARE_ULC
    case PH_FRINFC_MFUL_FMT_WR_TLV1:
        if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
        {
            /* Send length for write command is always Five */
            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
            /* Write command */
            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
            (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], 
                        NDEFTLV2,
                        PH_FRINFC_MFUL_FMT_VAL_4);
        }
        break;
    default:
        break;
#endif /* #ifdef PH_NDEF_MIFARE_ULC */

    
    }
}

static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
    NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
                                    NFCSTATUS_FORMAT_ERROR);
    uint32_t    memcompare = PH_FRINFC_MFUL_FMT_VAL_0;
    uint8_t     ZeroBuf[] = {0x00, 0x00, 0x00, 0x00};

#ifdef PH_NDEF_MIFARE_ULC
    uint8_t                 OTPByteUL[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
    uint8_t                 OTPByteULC[] = PH_FRINFC_MFULC_FMT_OTP_BYTES;
#endif /* #ifdef PH_NDEF_MIFARE_ULC */

    /* Check the lock bits (byte number 2 and 3 of block number 2) */
    if ((NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_2] == 
        PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL) && 
        (NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_3] == 
        PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL))
    {

#ifdef PH_NDEF_MIFARE_ULC

        if (NdefSmtCrdFmt->SendRecvBuf[8] == 0x02 && 
            NdefSmtCrdFmt->SendRecvBuf[9] == 0x00) 
        {
            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD;
            
            (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                        OTPByteULC,
                        sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
        }
        else if (NdefSmtCrdFmt->SendRecvBuf[8] == 0xFF && 
                NdefSmtCrdFmt->SendRecvBuf[9] == 0xFF)
        {
            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
            
            (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                        OTPByteUL,
                        sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
        }
        else
        {
            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
        }

#endif /* #ifdef PH_NDEF_MIFARE_ULC */

        memcompare = (uint32_t) 
                    MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
                            NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
                            PH_FRINFC_MFUL_FMT_VAL_4);

        if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
        {
            /* Write NDEF TLV in block number 4 */
            NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 
                                                PH_FRINFC_MFUL_FMT_VAL_4;
            /* Card already have the OTP bytes so write TLV */
            NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
        }
        else
        {
            /* IS the card new, OTP bytes = {0x00, 0x00, 0x00, 0x00} */
            memcompare = (uint32_t)MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
                                ZeroBuf,
                                PH_FRINFC_MFUL_FMT_VAL_4);
            /* If OTP bytes are Zero then the card is Zero */
            if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
            {
                /* Write OTP bytes in block number 3 */
                NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 
                                                PH_FRINFC_MFUL_FMT_VAL_3;
                /* Card already have the OTP bytes so write TLV */
                NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_OTPBYTES;
            }
        }
    }

    

#ifdef PH_NDEF_MIFARE_ULC
    if(
        ((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) || 
        (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES)) &&
        ((NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) ||
        (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD))
        )
#else
    if((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) || 
        (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES))
#endif /* #ifdef PH_NDEF_MIFARE_ULC */        
    {
        Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
    }
    return Result;
}

static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
{
    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
    /* Card already have the OTP bytes so write TLV */
    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;

    /* Write NDEF TLV in block number 4 */
    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 
                                PH_FRINFC_MFUL_FMT_VAL_4;

    Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
    return Result;
}