summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartijn Coenen <martijn.coenen@nxp.com>2011-01-13 10:49:03 +0100
committerNick Pelly <npelly@google.com>2011-01-18 11:17:30 -0800
commita6243755a9b438bfbfe0be331ece55953f8cf9eb (patch)
tree4797ff8929bca87c03d2a62ca1224f76eb74862e
parent72854a2c28b99f9ab6aa60c906d5b3c1a36b04d7 (diff)
downloadexternal_libnfc-nxp-a6243755a9b438bfbfe0be331ece55953f8cf9eb.zip
external_libnfc-nxp-a6243755a9b438bfbfe0be331ece55953f8cf9eb.tar.gz
external_libnfc-nxp-a6243755a9b438bfbfe0be331ece55953f8cf9eb.tar.bz2
Implement makeReadOnly() for dynamic T1T/T2T.
The NFC Forum Type 1 Tag and Type 2 Tag specification allows for tags with a dynamic memory layout. Support for making tags with the dynamic layout readonly has been added in this patch. Change-Id: I5bc8912d80f448fdea95e1ee21631c0f186ad79a
-rw-r--r--src/phFriNfc_MifULFormat.c925
-rw-r--r--src/phFriNfc_MifULFormat.h24
-rw-r--r--src/phFriNfc_NdefMap.c5
-rw-r--r--src/phFriNfc_NdefMap.h6
-rw-r--r--src/phFriNfc_SmtCrdFmt.h16
-rw-r--r--src/phFriNfc_TopazDynamicMap.c518
-rw-r--r--src/phFriNfc_TopazMap.c14
-rw-r--r--src/phFriNfc_TopazMap.h33
-rw-r--r--src/phLibNfc_ndef_raw.c21
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++)