diff options
-rw-r--r-- | src/phFriNfc_MifULFormat.c | 925 | ||||
-rw-r--r-- | src/phFriNfc_MifULFormat.h | 24 | ||||
-rw-r--r-- | src/phFriNfc_NdefMap.c | 5 | ||||
-rw-r--r-- | src/phFriNfc_NdefMap.h | 6 | ||||
-rw-r--r-- | src/phFriNfc_SmtCrdFmt.h | 16 | ||||
-rw-r--r-- | src/phFriNfc_TopazDynamicMap.c | 518 | ||||
-rw-r--r-- | src/phFriNfc_TopazMap.c | 14 | ||||
-rw-r--r-- | src/phFriNfc_TopazMap.h | 33 | ||||
-rw-r--r-- | src/phLibNfc_ndef_raw.c | 21 |
9 files changed, 1516 insertions, 46 deletions
diff --git a/src/phFriNfc_MifULFormat.c b/src/phFriNfc_MifULFormat.c index 899249d..3821b37 100644 --- a/src/phFriNfc_MifULFormat.c +++ b/src/phFriNfc_MifULFormat.c @@ -49,8 +49,61 @@ #define READ_ONLY_VALUE_IN_OTP 0x0FU /* Mifare UL OTP block number is 3 */ #define MIFARE_UL_READ_MAX_SIZE 16U - /* Lock byte value */ - #define MIFARE_UL_LOCK_BYTE_VALUE 0xFFU + /* 1st Lock byte value */ + #define MIFARE_UL_LOCK_BYTE1_VALUE 0xF8U + /* 2nd Lock byte value */ + #define MIFARE_UL_LOCK_BYTE2_VALUE 0xFFU + /* Mifare ULC dynamic lock byte address */ + #define MIFARE_ULC_DYNAMIC_LOCK_BYTES_ADDR 0x28U + /* Type 2 STATIC CARD memory value in the OTP */ + #define TYPE_2_STATIC_MEM_SIZE_VALUE 0x06U + /* Type 2 DYNAMIC CARD memory value in the OTP */ + #define TYPE_2_DYNAMIC_MEM_SIZE_VALUE 0x12U + /* Lock byte 3 value to be ORed with the existing value */ + #define MIFARE_UL_LOCK_BYTE3_VALUE 0xEEU + /* Posiiton of the memory information in the stored OTP bytes */ + #define TYPE_2_MEM_SIZE_POSITION 0x02U + /* 3rd Lock byte position after reading the block number 0x28 */ + #define TYPE_2_LOCK_BYTE3_POS_RD_BLK28 0x00U + +#ifdef PH_NDEF_MIFARE_ULC + + /* Lock control TLVs, TYPE identifier */ + #define LOCK_CTRL_TYPE_IN_TLV 0x01U + /* Lock control TLVs, Length expected */ + #define LOCK_CTRL_LEN_IN_TLV 0x03U + + /* NDEF message TLVs, TYPE identifier */ + #define NDEF_TYPE_IN_TLV 0x03U + + #define MFUL_NULL_TLV 0x00U + #define THREE_BYTE_LENGTH_FIELD 0xFFU + #define TERMINATOR_TLV 0xFEU + #define MIFARE_ULC_SIZE 0xC0U + #define MFUL_NIBBLE_SIZE 0x04U + #define MFUL_NIBBLE_MASK 0x0FU + #define MFUL_BYTE_SIZE_IN_BITS 0x08U + #define MFUL_BLOCK_SIZE_IN_BYTES 0x04U + /* Initial (0 to 3 blocks) 4 blocks are ignored, i.e., 16 bytes */ + #define MFUL_INITIAL_BYTES_IGNORED 0x10U + + #define MFUL_CONVERT_BITS_TO_BYTES(bits_to_bytes) \ + (((bits_to_bytes % MFUL_BYTE_SIZE_IN_BITS) > 0) ? \ + ((bits_to_bytes / MFUL_BYTE_SIZE_IN_BITS) + 1) : \ + (bits_to_bytes / MFUL_BYTE_SIZE_IN_BITS)) + + typedef enum phFriNfc_MfUL_Parse + { + LOCK_TLV_T, + LOCK_TLV_L, + LOCK_TLV_V, + NDEF_TLV_T, + NDEF_TLV_L, + NDEF_TLV_V + }phFriNfc_MfUL_Parse_t; + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + #endif /* #ifdef FRINFC_READONLY_NDEF */ /*! * \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the @@ -83,6 +136,53 @@ static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmt */ static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); +#ifdef FRINFC_READONLY_NDEF + +#ifdef PH_NDEF_MIFARE_ULC + +static +NFCSTATUS +phFriNfc_MfUL_ParseTLVs ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t *data_to_parse, + uint8_t size_to_parse); + +static +NFCSTATUS +phFriNfc_MfUL_GetLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_MfUL_GetDefaultLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +uint8_t +phFriNfc_MfUL_GetSkipSize ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t block_number, + uint8_t byte_number); + +static +NFCSTATUS +phFriNfc_MfUL_ReadWriteLockBytes ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_MfUL_UpdateAndWriteLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +uint8_t +phFriNfc_MfUL_CalcRemainingLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + 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*/ @@ -149,9 +249,12 @@ phFriNfc_MfUL_ConvertToReadOnly ( { NFCSTATUS result = NFCSTATUS_SUCCESS; + NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = TRUE; + NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0; + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_16BYTES; - result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt); + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); return result; } @@ -205,8 +308,10 @@ void phFriNfc_MfUL_Process(void *Context, (void *)NdefSmtCrdFmt->SendRecvBuf, sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes)); - NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = MIFARE_UL_LOCK_BYTE_VALUE; - NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = MIFARE_UL_LOCK_BYTE_VALUE; + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] + | MIFARE_UL_LOCK_BYTE1_VALUE); + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = MIFARE_UL_LOCK_BYTE2_VALUE; i = (uint8_t)(i + otp_lock_page_size); otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes); @@ -218,18 +323,146 @@ void phFriNfc_MfUL_Process(void *Context, NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[(otp_lock_page_size - 1)] = READ_ONLY_VALUE_IN_OTP; - NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES; - Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION]) + { + case TYPE_2_STATIC_MEM_SIZE_VALUE: + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + break; + } + +#ifdef PH_NDEF_MIFARE_ULC + case TYPE_2_DYNAMIC_MEM_SIZE_VALUE: + { + NdefSmtCrdFmt->State = + PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES; + + /* Start reading from block 4 */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 4; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + break; + } +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + default: + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); } break; } case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES: { - NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES; - Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION]) + { + case TYPE_2_STATIC_MEM_SIZE_VALUE: +#ifdef PH_NDEF_MIFARE_ULC + case TYPE_2_DYNAMIC_MEM_SIZE_VALUE: +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + break; + } + + default: + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + break; } +#ifdef PH_NDEF_MIFARE_ULC + + case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES: + { + if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength) + { + Status = phFriNfc_MfUL_ParseTLVs (NdefSmtCrdFmt, + NdefSmtCrdFmt->SendRecvBuf, + (uint8_t)*NdefSmtCrdFmt->SendRecvLength); + + if (!Status) + { + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + NdefSmtCrdFmt->AddInfo.Type2Info.LockBlockNumber; + Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt); + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES: + { + if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength) + { + (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.ReadData, + (void *)NdefSmtCrdFmt->SendRecvBuf, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.ReadData)); + + NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0; + + Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt); + + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES: + { + NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex + + MFUL_BLOCK_SIZE_IN_BYTES); + + if (!phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)) + { + /* There is no lock bits to write, then write OTP bytes */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + else if ((NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex < + MIFARE_UL_READ_MAX_SIZE) + && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt))) + { + /* If remaining lock bits has to be written and the data is already read */ + Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt); + } + else + { + /* Increment current block by 4 because if a data is read then 16 + bytes will be given which is 4 blocks */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4); + Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt); + } + break; + } + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES: { /* Do nothing */ @@ -257,6 +490,627 @@ void phFriNfc_MfUL_Process(void *Context, } } +#ifdef FRINFC_READONLY_NDEF + +#ifdef PH_NDEF_MIFARE_ULC + +static +uint8_t +phFriNfc_MfUL_GetSkipSize ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t block_number, + uint8_t byte_number) +{ + uint8_t skip_size = 0; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &NdefSmtCrdFmt->AddInfo.Type2Info; + + /* This check is added, because the default lock bits is always + present after the DATA AREA. + So, default lock bytes doesnt have any skip size */ + if (!ps_type2_info->DefaultLockBytesFlag) + { + /* Only check for the lock control TLV */ + if ((block_number == ps_type2_info->LockBlockNumber) + && (byte_number == ps_type2_info->LockByteNumber)) + { + skip_size = MFUL_CONVERT_BITS_TO_BYTES(ps_type2_info->NoOfLockBits); + } + } + + return skip_size; +} + +static +NFCSTATUS +phFriNfc_MfUL_GetLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint8_t page_address = 0; + uint8_t bytes_offset = 0; + uint8_t lock_index = 0; + + + page_address = (uint8_t)(ps_type2_info->DynLockBytes[lock_index] >> MFUL_NIBBLE_SIZE); + bytes_offset = (uint8_t)(ps_type2_info->DynLockBytes[lock_index] & MFUL_NIBBLE_MASK); + + lock_index = (lock_index + 1); + ps_type2_info->NoOfLockBits = ps_type2_info->DynLockBytes[lock_index]; + + lock_index = (lock_index + 1); + ps_type2_info->LockBytesPerPage = + (ps_type2_info->DynLockBytes[lock_index] & MFUL_NIBBLE_MASK); + ps_type2_info->BytesLockedPerLockBit = + (ps_type2_info->DynLockBytes[lock_index] >> MFUL_NIBBLE_SIZE); + + /* Apply the formula to calculate byte address + ByteAddr = ((PageAddr * (2 ^ BytesPerPage)) + ByteOffset) + */ + ps_type2_info->LockByteNumber = (uint8_t)((page_address + * (1 << ps_type2_info->LockBytesPerPage)) + + bytes_offset); + + ps_type2_info->LockBlockNumber = (uint8_t)(ps_type2_info->LockByteNumber / + MFUL_BLOCK_SIZE_IN_BYTES); + ps_type2_info->LockByteNumber = (uint8_t)(ps_type2_info->LockByteNumber % + MFUL_BLOCK_SIZE_IN_BYTES); + +#if 0 + if ( + /* Out of bound memory check */ + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) > + (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] * + TOPAZ_BYTES_PER_BLOCK)) || + + /* Check the static lock and reserved areas memory blocks */ + ((ps_locktlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) && + (ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) || + (((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) >= + TOPAZ_STATIC_LOCK_RES_START) && + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) < + TOPAZ_STATIC_LOCK_RES_END)) + ) + { + ps_locktlv_info->ByteAddr = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + ps_locktlv_info->BlkNum = (ps_locktlv_info->ByteAddr / + TOPAZ_BYTES_PER_BLOCK); + ps_locktlv_info->ByteNum = (ps_locktlv_info->ByteAddr % + TOPAZ_BYTES_PER_BLOCK); + } +#endif /* #if 0 */ + + return result; +} + +static +uint8_t +phFriNfc_MfUL_CalcRemainingLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + uint8_t lock_bits_remaining = 0; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + + lock_bits_remaining = (uint8_t)(ps_type2_info->NoOfLockBits - + ps_type2_info->LockBitsWritten); + + return lock_bits_remaining; +} + +static +NFCSTATUS +phFriNfc_MfUL_UpdateAndWriteLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint8_t byte_index = 0; + uint8_t no_of_bits_left_in_block = 0; + uint8_t remaining_lock_bits = 0; + uint8_t remaining_lock_bytes = 0; + /* Array of 3 is used because the lock bits with 4 bytes in a block + is handled in the function phFriNfc_MfUL_ReadWriteLockBytes + So use this function only if lock bytes doesnt use the entire block */ + uint8_t lock_bytes_value[MFUL_BLOCK_SIZE_IN_BYTES] = {0}; + uint8_t lock_byte_index = 0; + + (void)memcpy ((void *)lock_bytes_value, + (void*)(ps_type2_info->ReadData + ps_type2_info->ReadDataIndex), + sizeof (ps_type2_info->DynLockBytes)); + remaining_lock_bits = phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt); + + if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber) + { + /* 1st write to lock bits, so byte_index is updated */ + byte_index = ps_type2_info->LockByteNumber; + } + + no_of_bits_left_in_block = (uint8_t)((MFUL_BLOCK_SIZE_IN_BYTES - byte_index) * + MFUL_BYTE_SIZE_IN_BITS); + + if (no_of_bits_left_in_block >= remaining_lock_bits) + { + /* Entire lock bits can be written + if block size is more than number of lock bits. + so allocate the lock bits with value 1b and + dont change the remaining bits */ + if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) + { + /* mod operation has resulted in a value, means lock bits ends in between a byte */ + uint8_t mod_value = 0; + + remaining_lock_bytes = ((remaining_lock_bits / + MFUL_BYTE_SIZE_IN_BITS) + 1); + + /* mod_value is used to fill the only partial bits and + remaining bits shall be untouched */ + mod_value = (uint8_t)(remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS); + if (remaining_lock_bits > MFUL_BYTE_SIZE_IN_BITS) + { + /* lock bits to write is greater than 8 bits */ + while (lock_byte_index < (remaining_lock_bytes - 1)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + /* Last byte of the lock bits shall be filled partially, + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[byte_index] = 0; + lock_bytes_value[byte_index] = (uint8_t) + SET_BITS8 (lock_bytes_value[byte_index], 0, + mod_value, 1); + } + else + { + /* lock bits to write is less than 8 bits, so + there is only one byte to write. + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[0] = (uint8_t)SET_BITS8 (lock_bytes_value[0], 0, + mod_value, 1); + } + } /* if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */ + else + { + /* MOD operation is 00, that means entire byte value shall be 0xFF, means + every bit shall be to 1 */ + remaining_lock_bytes = (remaining_lock_bits / + MFUL_BYTE_SIZE_IN_BITS); + + while (lock_byte_index < remaining_lock_bytes) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + } /* else of if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */ + ps_type2_info->LockBitsWritten = (uint8_t)(ps_type2_info->LockBitsWritten + + remaining_lock_bits); + } /* if (no_of_bits_left_in_block >= remaining_lock_bits) */ + else + { + /* Update till the left bits in the block and then carry + out next operation after this write */ + while (lock_byte_index < (no_of_bits_left_in_block / MFUL_BYTE_SIZE_IN_BITS)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + ps_type2_info->LockBitsWritten = (uint8_t)(ps_type2_info->LockBitsWritten + + no_of_bits_left_in_block); + } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */ + + + /* Copy the values back to the DynLockBytes structure member */ + (void)memcpy ((void*)ps_type2_info->DynLockBytes, + (void *)lock_bytes_value, + sizeof (ps_type2_info->DynLockBytes)); + + + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES; + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + + return result; +} + +static +NFCSTATUS +phFriNfc_MfUL_ReadWriteLockBytes ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint8_t write_flag = FALSE; + + if (/* Lock bytes starts from the beginning of the block */ + (0 == ps_type2_info->LockByteNumber) + /* To make sure this is the first read */ + && (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber) + /* Lock bytes are greater than or equal to the block size, i.e., 4 bytes */ + && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt) + >= (MFUL_BLOCK_SIZE_IN_BYTES * MFUL_BYTE_SIZE_IN_BITS))) + { + /* Then directly write the lock bytes, dont waste time for read */ + (void)memset ((void *)ps_type2_info->DynLockBytes, 0xFF, + sizeof (ps_type2_info->DynLockBytes)); + write_flag = TRUE; + } + else if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber) + { + /* Read is mandatory, First read and then update the block, + because chances are there that lock byte may start in between + the block */ + } + else if (/* check if remaining bytes exceeds or same as the block size */ + (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt) + >= (MFUL_BLOCK_SIZE_IN_BYTES * MFUL_BYTE_SIZE_IN_BITS))) + { + /* Then directly write the lock bytes, dont waste time for read */ + (void)memset ((void *)ps_type2_info->DynLockBytes, 0xFF, + sizeof (ps_type2_info->DynLockBytes)); + write_flag = TRUE; + } + else + { + /* Read is mandatory, First read and then update the block */ + } + + if (write_flag) + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES; + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + else + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES; + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_MfUL_GetDefaultLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint16_t lock_byte_start_addr = 0; + + /* The position of the dynamic lock bits starts from + the first byte after the data area */ + lock_byte_start_addr = (uint16_t)(MFUL_INITIAL_BYTES_IGNORED + + (ps_type2_info->OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8)); + + ps_type2_info->LockBlockNumber = (uint8_t)(lock_byte_start_addr / + MFUL_BLOCK_SIZE_IN_BYTES); + ps_type2_info->LockByteNumber = (uint8_t)(lock_byte_start_addr % + MFUL_BLOCK_SIZE_IN_BYTES); + /* Default settings + NoOfLockBits = [(DataAreaSize - 48)/8] */ + ps_type2_info->NoOfLockBits = (uint8_t) + (((ps_type2_info->OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8) - 48)/8); + + return result; +} + +static +NFCSTATUS +phFriNfc_MfUL_ParseTLVs ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t *data_to_parse, + uint8_t size_to_parse) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + static uint8_t lock_mem_ndef_index = 0; + static uint8_t skip_lock_mem_size = 0; + static uint16_t card_size_remaining = 0; + static uint16_t ndef_data_size = 0; + static phFriNfc_MfUL_Parse_t parse_tlv = LOCK_TLV_T; + uint8_t parse_index = 0; + + if ((0 == card_size_remaining) && (0 == parse_index)) + { + /* card size is calculated only once */ + card_size_remaining = (uint16_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8); + } + + while ((parse_index < size_to_parse) + && (NFCSTATUS_SUCCESS == result) + && (NDEF_TLV_V != parse_tlv) + && (0 != card_size_remaining)) + { + if (0 == skip_lock_mem_size) + { + /* Skip the lock TLVs, so get the lock bits */ + skip_lock_mem_size = phFriNfc_MfUL_GetSkipSize (NdefSmtCrdFmt, + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock, + parse_index); + } + + if (0 != skip_lock_mem_size) + { + if (skip_lock_mem_size >= (size_to_parse - parse_index)) + { + /* if skip size is more than the size to parse, then */ + card_size_remaining = (uint16_t)(card_size_remaining - + (size_to_parse - parse_index)); + skip_lock_mem_size = (uint8_t)(skip_lock_mem_size - + ((size_to_parse - parse_index))); + parse_index = size_to_parse; + } + else + { + card_size_remaining = (uint16_t)(card_size_remaining - + skip_lock_mem_size); + + parse_index = (uint8_t)(parse_index + skip_lock_mem_size); + skip_lock_mem_size = 0; + } + } + else + { + switch (parse_tlv) + { + case LOCK_TLV_T: + { + switch (*(data_to_parse + parse_index)) + { + case MFUL_NULL_TLV: + { + /* Do nothing, parse further */ + break; + } + + case LOCK_CTRL_TYPE_IN_TLV: + { + parse_tlv = LOCK_TLV_L; + break; + } + + case NDEF_TYPE_IN_TLV: + { + parse_tlv = NDEF_TLV_T; + /* Default lock bytes shall be taken */ + NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = + TRUE; + result = phFriNfc_MfUL_GetDefaultLockBytesInfo (NdefSmtCrdFmt); + break; + } + + default: + { + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + break; + } + + case LOCK_TLV_L: + { + if (LOCK_CTRL_LEN_IN_TLV == *(data_to_parse + parse_index)) + { + parse_tlv = LOCK_TLV_V; + } + else + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + } + break; + } + + case LOCK_TLV_V: + { + switch (lock_mem_ndef_index) + { + case 0: + case 1: + { + NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = + FALSE; + NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes[lock_mem_ndef_index] = + *(data_to_parse + parse_index); + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + break; + } + + case 2: + { + NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes[lock_mem_ndef_index] = + *(data_to_parse + parse_index); + parse_tlv = NDEF_TLV_T; + lock_mem_ndef_index = 0; + result = phFriNfc_MfUL_GetLockBytesInfo (NdefSmtCrdFmt); + break; + } + + default: + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + break; + } /* switch (lock_mem_ndef_index) in case LOCK_TLV_V */ + + case NDEF_TLV_T: + { + switch (*(data_to_parse + parse_index)) + { + case MFUL_NULL_TLV: + { + /* Do nothing, parse further */ + break; + } + + case NDEF_TYPE_IN_TLV: + { + parse_tlv = NDEF_TLV_L; + break; + } + + default: + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + break; + } /* switch (*(data_to_parse + parse_index)) in case NDEF_TLV_T */ + + case NDEF_TLV_L: + { + switch (lock_mem_ndef_index) + { + case 0: + { + if (THREE_BYTE_LENGTH_FIELD == *(data_to_parse + parse_index)) + { + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + } + else + { + ndef_data_size = *(data_to_parse + parse_index); + parse_tlv = NDEF_TLV_V; + lock_mem_ndef_index = 0; + } + break; + } + + case 1: + { + ndef_data_size = (uint16_t)(*(data_to_parse + parse_index) << 8); + break; + } + + case 2: + { + ndef_data_size = (uint16_t)(ndef_data_size | + *(data_to_parse + parse_index)); + parse_tlv = NDEF_TLV_V; + lock_mem_ndef_index = 0; + break; + } + } /* switch (lock_mem_ndef_index) in case NDEF_TLV_L */ + break; + } + + case NDEF_TLV_V: + { + break; + } + + default: + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } /* switch (parse_tlv) */ + + } /* else part of if (0 != skip_lock_mem_size) */ + + if (0 == card_size_remaining) + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else if (NDEF_TLV_V != parse_tlv) + { + /* Increment the index */ + parse_index = (uint8_t)(parse_index + 1); + /* card size is decremented as the memory area is parsed */ + card_size_remaining = (uint16_t)(card_size_remaining - 1); + } + else + { + /* L field of the NDEF TLV + L field can have 1 byte or also 3 bytes + */ + uint8_t length_to_deduct = 1; + + if ((NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION] + * 8) >= THREE_BYTE_LENGTH_FIELD) + { + length_to_deduct = 3; + } + /* parse_tlv has reached the VALUE field of the NDEF TLV */ + if ((card_size_remaining - length_to_deduct) < ndef_data_size) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + } + + lock_mem_ndef_index = 0; + skip_lock_mem_size = 0; + card_size_remaining = 0; + } + } /* while ((parse_index < size_to_parse) + && (NFCSTATUS_SUCCESS != result) + && (NDEF_TLV_V != parse_tlv) + && (0 != card_size_remaining)) */ + + if ((NDEF_TLV_V == parse_tlv) || (NFCSTATUS_SUCCESS != result)) + { + parse_tlv = LOCK_TLV_T; + } + else + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES; + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4); + + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + + if (NFCSTATUS_PENDING != result) + { + lock_mem_ndef_index = 0; + skip_lock_mem_size = 0; + card_size_remaining = 0; + } + return result; +} + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) { NFCSTATUS Result = NFCSTATUS_SUCCESS; @@ -266,7 +1120,7 @@ static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock); /* Call transceive */ - Result = phFriNfc_MfUL_H_Transceive(NdefSmtCrdFmt); + Result = phFriNfc_MfUL_H_Transceive (NdefSmtCrdFmt); return Result; } @@ -331,6 +1185,57 @@ static void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFm break; } +#ifdef PH_NDEF_MIFARE_ULC + + case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + *NdefSmtCrdFmt->SendRecvBuf = + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock; + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1; + break; + } + + case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock; + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1; + break; + } + + case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; +#else + /* Write command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock; + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes, + PH_FRINFC_MFUL_FMT_VAL_4); + break; + } + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES: { #ifdef PH_HAL4_ENABLE diff --git a/src/phFriNfc_MifULFormat.h b/src/phFriNfc_MifULFormat.h index 9307523..5238014 100644 --- a/src/phFriNfc_MifULFormat.h +++ b/src/phFriNfc_MifULFormat.h @@ -53,17 +53,25 @@ * */ /*@{*/ -#define PH_FRINFC_MFUL_FMT_RESET_INIT 0 /*!< Reset state */ -#define PH_FRINFC_MFUL_FMT_RD_16BYTES 1 /*!< Read 16 bytes */ -#define PH_FRINFC_MFUL_FMT_WR_OTPBYTES 2 /*!< Write OTP bytes */ -#define PH_FRINFC_MFUL_FMT_WR_TLV 3 /*!< Write TLV */ +#define PH_FRINFC_MFUL_FMT_RESET_INIT 0 /*!< Reset state */ +#define PH_FRINFC_MFUL_FMT_RD_16BYTES 1 /*!< Read 16 bytes */ +#define PH_FRINFC_MFUL_FMT_WR_OTPBYTES 2 /*!< Write OTP bytes */ +#define PH_FRINFC_MFUL_FMT_WR_TLV 3 /*!< Write TLV */ #ifdef PH_NDEF_MIFARE_ULC -#define PH_FRINFC_MFUL_FMT_WR_TLV1 4 /*!< Write TLV (second part) */ +#define PH_FRINFC_MFUL_FMT_WR_TLV1 4 /*!< Write TLV (second part) */ #endif /* #ifdef PH_NDEF_MIFARE_ULC */ #ifdef FRINFC_READONLY_NDEF -#define PH_FRINFC_MFUL_FMT_RO_RD_16BYTES 5 /*!< Read only the tag */ -#define PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES 6 /*!< Write lock bytes to make the tag Read only */ -#define PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES 7 /*!< Write OTP bytes to make the tag Read only */ +#define PH_FRINFC_MFUL_FMT_RO_RD_16BYTES 5 /*!< Read only the tag */ +#define PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES 6 /*!< Write lock bytes to make the tag Read only */ +#define PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES 7 /*!< Write OTP bytes to make the tag Read only */ + +#ifdef PH_NDEF_MIFARE_ULC +#define PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES 8 /*!< Read default dynamic lock bytes address */ +#define PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES 9 /*!< Write default dynamic lock bytes address */ +#define PH_FRINFC_MFUL_FMT_RO_PARSE_NDEF 10 /*!< Write default dynamic lock bytes address */ +#define PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES 12 /*!< Read bytes from the card for parsing NDEF */ +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + #endif /* #ifdef FRINFC_READONLY_NDEF */ /*@}*/ diff --git a/src/phFriNfc_NdefMap.c b/src/phFriNfc_NdefMap.c index d1fb133..88cf5ff 100644 --- a/src/phFriNfc_NdefMap.c +++ b/src/phFriNfc_NdefMap.c @@ -646,6 +646,11 @@ phFriNfc_NdefMap_ConvertToReadOnly ( } case PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD: + { + result = phFriNfc_TopazDynamicMap_ConvertToReadOnly (NdefMap); + break; + } + default: { result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, diff --git a/src/phFriNfc_NdefMap.h b/src/phFriNfc_NdefMap.h index e58e338..a7d3459 100644 --- a/src/phFriNfc_NdefMap.h +++ b/src/phFriNfc_NdefMap.h @@ -53,7 +53,7 @@ * */ /*@{*/ -#define PH_FRINFC_NDEFMAP_FILEREVISION "$Revision: 1.24 $" /**< \ingroup grp_file_attributes */ +#define PH_FRINFC_NDEFMAP_FILEREVISION "$Revision: 1.25 $" /**< \ingroup grp_file_attributes */ #define PH_FRINFC_NDEFMAP_FILEALIASES "$Aliases: $" /**< \ingroup grp_file_attributes */ /*@}*/ @@ -739,6 +739,10 @@ typedef struct phFriNfc_TopazCont then this variable is used. */ uint16_t RemainingReadSize; +#ifdef FRINFC_READONLY_NDEF + uint8_t read_only_seq; + uint8_t lock_bytes_written; +#endif /* #ifdef FRINFC_READONLY_NDEF */ }phFriNfc_TopazCont_t; diff --git a/src/phFriNfc_SmtCrdFmt.h b/src/phFriNfc_SmtCrdFmt.h index ebf870d..46b0d0d 100644 --- a/src/phFriNfc_SmtCrdFmt.h +++ b/src/phFriNfc_SmtCrdFmt.h @@ -143,7 +143,21 @@ typedef struct phFriNfc_Type2_AddInfo /* Stores the CC byte values. For Ex: 0xE1, 0x10 , 0x10, 0x00*/ uint8_t OTPBytes[4]; #ifdef FRINFC_READONLY_NDEF - uint8_t LockBytes[4]; + uint8_t LockBytes[4]; + +#ifdef PH_NDEF_MIFARE_ULC + uint8_t ReadData[16]; + uint8_t ReadDataIndex; + uint8_t DynLockBytes[4]; + uint8_t BytesLockedPerLockBit; + uint8_t LockBytesPerPage; + uint8_t LockByteNumber; + uint8_t LockBlockNumber; + uint8_t NoOfLockBits; + uint8_t DefaultLockBytesFlag; + uint8_t LockBitsWritten; +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + #endif /* #ifdef FRINFC_READONLY_NDEF */ /* Current Block Address*/ uint8_t CurrentBlock; diff --git a/src/phFriNfc_TopazDynamicMap.c b/src/phFriNfc_TopazDynamicMap.c index dc99a43..697604d 100644 --- a/src/phFriNfc_TopazDynamicMap.c +++ b/src/phFriNfc_TopazDynamicMap.c @@ -20,10 +20,10 @@ * * Project: NFC-FRI * -* $Date: Tue Jun 8 17:19:18 2010 $ +* $Date: Wed Oct 27 10:21:29 2010 $ * $Author: ing02260 $ -* $Revision: 1.38 $ -* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* $Revision: 1.41 $ +* $Aliases: $ * */ @@ -43,8 +43,8 @@ * */ /*@{*/ -#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.38 $" -#define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1023_R35_1 $" +#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.41 $" +#define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: $" /*@}*/ /*! * \name Topaz Mapping - Helper data structures and macros @@ -53,7 +53,21 @@ /*@{*/ /********************************** Start of data structures *********************************/ +#ifdef FRINFC_READONLY_NDEF + #define DYN_CC_BLOCK_NUMBER (0x01U) + #define DYN_STATIC_LOCK_BLOCK_NUM (0x0EU) + + #define DYN_STATIC_LOCK0_BYTE_NUM (0x00U) + #define DYN_STATIC_LOCK0_BYTE_VALUE (0xFFU) + + #define DYN_STATIC_LOCK1_BYTE_NUM (0x01U) + #define DYN_STATIC_LOCK1_BYTE_VALUE (0x7FU) + + #define DYN_CC_RWA_BYTE_NUMBER (0x03U) + #define DYN_CC_READ_ONLY_VALUE (0x0FU) + +#endif /* #ifdef FRINFC_READONLY_NDEF */ /*! * \brief \copydoc page_ovr enum for the topaz sequence of execution. @@ -86,12 +100,30 @@ typedef enum phFriNfc_Tpz_WrSeq WR_NMN_E1 }phFriNfc_Tpz_WrSeq_t; +#ifdef FRINFC_READONLY_NDEF + +typedef enum phFriNfc_Tpz_RO_Seq +{ + WR_READONLY_CC, + RD_LOCK_BYTES, + WR_LOCK_BYTES, + RD_STATIC_LOCK_BYTE0, + WR_STATIC_LOCK_BYTE0, + WR_STATIC_LOCK_BYTE1 +}phFriNfc_Tpz_RO_Seq_t; + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + /********************************** End of data structures *********************************/ /********************************** Start of Macros *********************************/ /* New state for TOPAZ dynamic card*/ #define PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF (0x10U) +#ifdef FRINFC_READONLY_NDEF + #define PH_FRINFC_TOPAZ_STATE_READ_ONLY (0x11U) +#endif /* #ifdef FRINFC_READONLY_NDEF */ + #define NIBBLE_SIZE (0x04U) /* Byte shifting for the topaz */ #define TOPAZ_BYTE_SHIFT (0x08U) @@ -110,7 +142,7 @@ typedef enum phFriNfc_Tpz_WrSeq /* First lock or reserved byte number in the static area of the card */ #define TOPAZ_STATIC_LOCK_RES_START (0x68U) /* End lock or reserved byte number in the static area of the card */ -#define TOPAZ_STATIC_LOCK_RES_END (0x80U) +#define TOPAZ_STATIC_LOCK_RES_END (0x78U) /* CC byte length */ #define TOPAZ_CC_BYTES_LENGTH (0x04U) @@ -168,6 +200,14 @@ so there are 4 segements in the card */ (((block_no) + 1) + TOPAZ_STATIC_LOCK_BLOCK_AREAS) : \ ((block_no) + 1)) +#ifdef FRINFC_READONLY_NDEF + +#define TOPAZ_CONVERT_BITS_TO_BYTES(bits_to_bytes) \ + (((bits_to_bytes % TOPAZ_BYTE_SIZE_IN_BITS) > 0) ? \ + ((bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS) + 1) : \ + (bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS)) + +#endif /* #ifdef FRINFC_READONLY_NDEF */ /********************************** End of Macros *********************************/ /*@}*/ @@ -489,6 +529,21 @@ NFCSTATUS phFriNfc_Tpz_H_UpdateNdefTypeField ( phFriNfc_NdefMap_t *psNdefMap); +#ifdef FRINFC_READONLY_NDEF + +static +NFCSTATUS +phFriNfc_Tpz_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateAndWriteLockBits ( + phFriNfc_NdefMap_t *psNdefMap); + + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + /*! * \brief Check whether a particular Remote Device is NDEF compliant. @@ -522,6 +577,12 @@ NFCSTATUS phFriNfc_TopazDynamicMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) NdefMap->TopazContainer.WriteSeq = 0; NdefMap->TopazContainer.ExpectedSeq = 0; + (void)memset ((void *)&(NdefMap->LockTlv), 0, + sizeof (phFriNfc_LockCntrlTLVCont_t)); + + (void)memset ((void *)&(NdefMap->MemTlv), 0, + sizeof (phFriNfc_ResMemCntrlTLVCont_t)); + /* Set card state */ NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD; @@ -649,6 +710,44 @@ NFCSTATUS phFriNfc_TopazDynamicMap_RdNdef( phFriNfc_NdefMap_t *NdefMap return Result; } +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_TopazDynamicMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t cc_read_only_byte = 0x0FU; + + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ_ONLY; + + psNdefMap->TopazContainer.read_only_seq = 0; + + + + psNdefMap->TopazContainer.CurrentBlock = 0x01U; + psNdefMap->TopazContainer.ByteNumber = 0x03U; + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &cc_read_only_byte, + 1); + + if (NFCSTATUS_PENDING == result) + { + psNdefMap->TopazContainer.read_only_seq = (uint8_t)WR_READONLY_CC; + } + + + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + /*! * \brief Initiates Writing of NDEF information to the Remote Device. * @@ -793,6 +892,14 @@ void phFriNfc_TopazDynamicMap_Process( void *Context, Status = phFriNfc_Tpz_H_ChkReadID(NdefMap); break; } + +#ifdef FRINFC_READONLY_NDEF + case PH_FRINFC_TOPAZ_STATE_READ_ONLY: + { + Status = phFriNfc_Tpz_H_ProcessReadOnly (NdefMap); + break; + } +#endif /* #ifdef FRINFC_READONLY_NDEF */ default: { @@ -810,6 +917,364 @@ void phFriNfc_TopazDynamicMap_Process( void *Context, } } +#ifdef FRINFC_READONLY_NDEF + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateAndWriteLockBits ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + uint8_t remaining_lock_bits = 0; + uint8_t byte_index = 0; + uint8_t lock_bytes_value[TOPAZ_BYTES_PER_BLOCK] = {0}; + uint8_t lock_byte_index = 0; + uint8_t no_of_bits_left_in_block = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + ps_locktlv_info = &(psNdefMap->LockTlv); + + (void)memcpy ((void *)lock_bytes_value, (void *)psNdefMap->SendRecvBuf, + TOPAZ_BYTES_PER_BLOCK); + + if (ps_tpz_info->CurrentBlock == ps_locktlv_info->BlkNum) + { + /* Get the lock bits that has to locked */ + remaining_lock_bits = ps_locktlv_info->LockTlvBuff[1]; + byte_index = (uint8_t)ps_locktlv_info->ByteNum; + } + else + { + /* This condition applies only for the lock bits not ending with + " ps_locktlv_info->BlkNum ". + Calculate the remaining lock bits */ + remaining_lock_bits = (uint8_t)(ps_locktlv_info->LockTlvBuff[1] - + ps_tpz_info->lock_bytes_written); + } + + no_of_bits_left_in_block = (uint8_t)((TOPAZ_BYTES_PER_BLOCK - byte_index) * + TOPAZ_BYTE_SIZE_IN_BITS); + + if (no_of_bits_left_in_block >= remaining_lock_bits) + { + /* Entire lock bits can be written */ + uint8_t mod_value = 0; + + mod_value = (uint8_t)(remaining_lock_bits % TOPAZ_BYTES_PER_BLOCK); + + if (mod_value) + { + /* The lock bits ends in between of a byte */ + /* lock bits to write is greater than 8 bits */ + if (mod_value > TOPAZ_BYTE_SIZE_IN_BITS) + { + while (lock_byte_index < + (TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits) - 1)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + /* Last byte of the lock bits shall be filled partially, + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[byte_index] = 0; + lock_bytes_value[byte_index] = (uint8_t) + SET_BITS8 (lock_bytes_value[byte_index], 0, + mod_value, 1); + } + else + { + /* lock bits to write is less than 8 bits, so + there is only one byte to write. + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[0] = (uint8_t) + SET_BITS8 (lock_bytes_value[0], 0, + mod_value, 1); + } + } /* if (mod_value) */ + else + { + /* The lock bits exactly ends at a byte + MOD operation is 00, that means entire byte value shall be 0xFF, means + every bit shall be to 1 */ + + while (lock_byte_index < TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + } /* else of /* if (mod_value) */ + ps_tpz_info->lock_bytes_written = remaining_lock_bits; + } + else /* if (no_of_bits_left_in_block >= remaining_lock_bits) */ + { + /* Partial lock bits can be written. use next read to write + the remaining lock bits */ + while (lock_byte_index < (no_of_bits_left_in_block / + TOPAZ_BYTES_PER_BLOCK)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + ps_tpz_info->lock_bytes_written = (uint8_t)(no_of_bits_left_in_block / + TOPAZ_BYTES_PER_BLOCK); + } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */ + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, lock_bytes_value, + sizeof (lock_bytes_value)); + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Tpz_RO_Seq_t e_readonly_seq = RD_LOCK_BYTES; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + static uint8_t static_lock_bytes[2] = {0}; + + ps_tpz_info = &(psNdefMap->TopazContainer); + ps_locktlv_info = &(psNdefMap->LockTlv); + e_readonly_seq = (phFriNfc_Tpz_RO_Seq_t)psNdefMap->TopazContainer.read_only_seq; + + switch (e_readonly_seq) + { + case WR_READONLY_CC: + { + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + psNdefMap->TopazContainer.CurrentBlock = (uint8_t) + psNdefMap->LockTlv.BlkNum; + + e_readonly_seq = RD_LOCK_BYTES; +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case RD_LOCK_BYTES: + { + if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) + { + result = phFriNfc_Tpz_H_UpdateAndWriteLockBits (psNdefMap); + + if (NFCSTATUS_PENDING == result) + { + e_readonly_seq = WR_LOCK_BYTES; + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_LOCK_BYTES: + { + if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength) + { + ps_tpz_info->CurrentBlock = (uint8_t) + (ps_tpz_info->CurrentBlock + 1); + if (ps_locktlv_info->LockTlvBuff[1] - + ps_tpz_info->lock_bytes_written) + { +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + e_readonly_seq = RD_LOCK_BYTES; + } + else + { + ps_tpz_info->CurrentBlock = (uint8_t) + DYN_STATIC_LOCK_BLOCK_NUM; + ps_tpz_info->ByteNumber = (uint8_t) + DYN_STATIC_LOCK0_BYTE_NUM; +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + e_readonly_seq = RD_STATIC_LOCK_BYTE0; + + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case RD_STATIC_LOCK_BYTE0: + { + if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) + { + uint8_t lock_byte_value = 0; + + (void)memcpy ((void *)static_lock_bytes, + (void *)(psNdefMap->SendRecvBuf + + ps_tpz_info->ByteNumber), + sizeof (static_lock_bytes)); + + + lock_byte_value = (uint8_t)(static_lock_bytes[0] | + DYN_STATIC_LOCK0_BYTE_VALUE); + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value, + 1); + + if (NFCSTATUS_PENDING == result) + { + e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE0; + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_STATIC_LOCK_BYTE0: + { + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + uint8_t lock_byte_value = + (static_lock_bytes[1] | + DYN_STATIC_LOCK1_BYTE_VALUE); + + ps_tpz_info->CurrentBlock = (uint8_t) + DYN_STATIC_LOCK_BLOCK_NUM; + ps_tpz_info->ByteNumber = (uint8_t) + DYN_STATIC_LOCK1_BYTE_NUM; +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value, + 1); + + if (NFCSTATUS_PENDING == result) + { + e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE1; + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_STATIC_LOCK_BYTE1: + { + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + /* READ ONLY successful */ + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + break; + } + } + + psNdefMap->TopazContainer.read_only_seq = (uint8_t)e_readonly_seq; + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + static NFCSTATUS phFriNfc_Tpz_H_ProWrResp ( @@ -1278,7 +1743,7 @@ phFriNfc_Tpz_H_ChkReadID( compare_result = phOsalNfc_MemCompare ( psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid, &psNdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], - psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength); + TOPAZ_UID_LENGTH_FOR_READ_WRITE); if (0 == compare_result) { /* State has to be changed */ @@ -1449,9 +1914,9 @@ phFriNfc_Tpz_H_NxpRead ( (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid, - psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength); + TOPAZ_UID_LENGTH_FOR_READ_WRITE); send_index = (uint8_t)(send_index + - psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength); + TOPAZ_UID_LENGTH_FOR_READ_WRITE); } psNdefMap->SendLength = send_index; @@ -1570,9 +2035,8 @@ phFriNfc_Tpz_H_NxpWrite( (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid, - psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength); - send_index = (uint8_t)(send_index + - psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength); + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + send_index = (uint8_t)(send_index + TOPAZ_UID_LENGTH_FOR_READ_WRITE); #endif /* #ifdef TOPAZ_RAW_SUPPORT */ @@ -2128,9 +2592,9 @@ phFriNfc_Tpz_H_CopyReadData ( phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (psNdefMap)) == ps_tpz_info->CurrentSeg) { - copy_index = (uint16_t)( + copy_index = (uint16_t)(copy_index + ( phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead ( - psNdefMap) % TOPAZ_SEGMENT_READ_LENGTH); + psNdefMap) % TOPAZ_SEGMENT_READ_LENGTH)); skip_size = 0; } @@ -2159,7 +2623,11 @@ phFriNfc_Tpz_H_CopyReadData ( <= ps_locktlv_info->ByteAddr) ) { - copy_till_address = ps_locktlv_info->ByteAddr; + if ((ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) || + (ps_locktlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8))) + { + copy_till_address = ps_locktlv_info->ByteAddr; + } skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, ps_locktlv_info->ByteAddr); } @@ -2179,10 +2647,14 @@ phFriNfc_Tpz_H_CopyReadData ( <= ps_memtlv_info->ByteAddr) ) { - copy_till_address = (uint16_t) + if ((ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) || + (ps_memtlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8))) + { + copy_till_address = (uint16_t) (((ps_memtlv_info->ByteAddr < copy_till_address) || (0 == copy_till_address))? ps_memtlv_info->ByteAddr : copy_till_address); + } if (copy_till_address == ps_memtlv_info->ByteAddr) { @@ -2286,6 +2758,11 @@ phFriNfc_Tpz_H_CopyReadData ( } } + if (copy_index != copy_till_address) + { + skip_size = 0; + } + if ((copy_index + skip_size) <= recv_length) { copy_index = (uint16_t)(copy_index + skip_size); @@ -2455,6 +2932,10 @@ phFriNfc_Tpz_H_ParseTLVs ( /* All the 3 bytes are copied in the local buffer */ if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index) { +#ifdef FRINFC_READONLY_NDEF + (void)memcpy ((void *)psNdefMap->LockTlv.LockTlvBuff, + (void *)lock_mem_buf, sizeof (lock_mem_buf)); +#endif /* #ifdef FRINFC_READONLY_NDEF */ /* Calculate the byte address and size of the lock bytes */ result = phFriNfc_Tpz_H_GetLockBytesInfo (psNdefMap, lock_mem_buf); lock_mem_ndef_index = 0; @@ -2712,6 +3193,7 @@ phFriNfc_Tpz_H_ParseTLVs ( ps_tpz_info->NDEFRWSize = (uint16_t) (ps_tpz_info->NDEFRWSize - 2); ndef_tlv_byte_addr = 0; + result = NFCSTATUS_SUCCESS; } } } @@ -3683,7 +4165,7 @@ phFriNfc_Tpz_H_GetLockBytesInfo ( ByteAddr = PageAddr*2^BytesPerPage + ByteOffset */ ps_locktlv_info->ByteAddr = (uint16_t)((page_address - * (2 << ps_locktlv_info->BytesPerPage)) + * (1 << ps_locktlv_info->BytesPerPage)) + bytes_offset); @@ -3746,7 +4228,7 @@ phFriNfc_Tpz_H_GetMemBytesInfo ( ByteAddr = PageAddr * 2^BytesPerPage + ByteOffset */ ps_memtlv_info->ByteAddr = (uint16_t)((page_address - * (2 << ps_memtlv_info->BytesPerPage)) + * (1 << ps_memtlv_info->BytesPerPage)) + bytes_offset); diff --git a/src/phFriNfc_TopazMap.c b/src/phFriNfc_TopazMap.c index 78828ec..8a0cc5f 100644 --- a/src/phFriNfc_TopazMap.c +++ b/src/phFriNfc_TopazMap.c @@ -526,6 +526,7 @@ void phFriNfc_TopazMap_Process( void *Context, if((CC_READ_ONLY_VALUE == *psNdefMap->SendRecvBuf) && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength)) { + written_lock_byte = 0; #ifdef TOPAZ_RAW_SUPPORT *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ; #else @@ -1262,8 +1263,17 @@ static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap) } else { - Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, - NFCSTATUS_INVALID_FORMAT)); + Result = NFCSTATUS_SUCCESS; + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + NdefMap->CardMemSize = + NdefMap->TopazContainer.RemainingSize = (uint16_t) + /* + 4 is decremented from the max size because of the 4 CC bytes + 2 is decremented because of the NDEF TLV T and L byte + to get the actual data size + */ + (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4 - + PH_FRINFC_TOPAZ_VAL2); } break; diff --git a/src/phFriNfc_TopazMap.h b/src/phFriNfc_TopazMap.h index 263095a..eb503f8 100644 --- a/src/phFriNfc_TopazMap.h +++ b/src/phFriNfc_TopazMap.h @@ -597,6 +597,39 @@ NFCSTATUS phFriNfc_TopazDynamicMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap); */ void phFriNfc_TopazDynamicMap_Process( void *Context, NFCSTATUS Status); + +#ifdef FRINFC_READONLY_NDEF +/*! + * \brief \copydoc page_ovr 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 phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] psNdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS +phFriNfc_TopazDynamicMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); +#endif /* #ifdef FRINFC_READONLY_NDEF */ + #endif /* PHFRINFC_TOPAZMAP_H */ diff --git a/src/phLibNfc_ndef_raw.c b/src/phLibNfc_ndef_raw.c index 6b7bfe5..1da598a 100644 --- a/src/phLibNfc_ndef_raw.c +++ b/src/phLibNfc_ndef_raw.c @@ -300,8 +300,8 @@ void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status) { gpphLibContext->status.GenCb_pending_status = FALSE; if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) { - gpphLibContext->psBufferedAuth->addr = (uint8_t) - gpphLibContext->ndef_cntx.psNdefMap->StdMifareContainer.currentBlock; + gpphLibContext->psBufferedAuth->addr = (uint8_t) + gpphLibContext->ndef_cntx.psNdefMap->StdMifareContainer.currentBlock; } if(NFCSTATUS_FAILED == status ) @@ -580,10 +580,15 @@ void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status) gpphLibContext->ndef_cntx.NdefLength) { status = NFCSTATUS_NOT_ENOUGH_MEMORY; - } - } - else - { + } + else + { + pLibNfc_Ctxt->ndef_cntx.NdefActualSize = + pLibNfc_Ctxt->ndef_cntx.psUpperNdefMsg->length; + } + } + else + { gpphLibContext->LastTrancvSuccess = FALSE; status = NFCSTATUS_FAILED;; } @@ -1437,6 +1442,9 @@ phLibNfc_ConvertToReadOnlyNdef ( case phHal_eJewel_PICC: { +// MC: Got the feedback this was #if 0'd because it was resetting the lock bits +// read in check NDEF, and these should not be reset here already. +#if 0 static uint16_t data_cnt = 0; /* Resets the component instance */ @@ -1449,6 +1457,7 @@ phLibNfc_ConvertToReadOnlyNdef ( gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, &(gpphLibContext->ndef_cntx.NdefSendRecvLen), &(data_cnt)); +#endif /* #if 0 */ for (fun_id = 0; fun_id < PH_FRINFC_NDEFMAP_CR; fun_id++) |