2 * Copyright (C) 2010 NXP Semiconductors
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * \file phFriNfc_MifULFormat.c
19 * \brief NFC Ndef Formatting For Mifare ultralight card.
23 * $Date: Mon Dec 13 14:14:12 2010 $
30 #include <phFriNfc_MifULFormat.h>
31 #include <phFriNfc_OvrHal.h>
33 /*! \ingroup grp_file_attributes
36 * File: \ref phFriNfc_MifULFormat.c
40 #define PHFRINFCMIFULFORMAT_FILEREVISION "$Revision: 1.9 $"
41 #define PHFRINFCMIFULFORMAT_FILEALIASES "$Aliases: $"
44 #ifdef FRINFC_READONLY_NDEF
45 /* Mifare UL OTP block number is 3 */
46 #define RD_LOCK_OTP_BLOCK_NUMBER 0x02U
47 #define OTP_BLOCK_NUMBER 0x03U
48 /* READ ONLY value that shall be written in the OTP to make the card read only */
49 #define READ_ONLY_VALUE_IN_OTP 0x0FU
50 /* Mifare UL OTP block number is 3 */
51 #define MIFARE_UL_READ_MAX_SIZE 16U
52 /* 1st Lock byte value */
53 #define MIFARE_UL_LOCK_BYTE1_VALUE 0xF8U
54 /* 2nd Lock byte value */
55 #define MIFARE_UL_LOCK_BYTE2_VALUE 0xFFU
56 /* Mifare ULC dynamic lock byte address */
57 #define MIFARE_ULC_DYNAMIC_LOCK_BYTES_ADDR 0x28U
58 /* Type 2 STATIC CARD memory value in the OTP */
59 #define TYPE_2_STATIC_MEM_SIZE_VALUE 0x06U
60 /* Type 2 DYNAMIC CARD memory value in the OTP */
61 #define TYPE_2_DYNAMIC_MEM_SIZE_VALUE 0x12U
62 /* Lock byte 3 value to be ORed with the existing value */
63 #define MIFARE_UL_LOCK_BYTE3_VALUE 0xEEU
64 /* Posiiton of the memory information in the stored OTP bytes */
65 #define TYPE_2_MEM_SIZE_POSITION 0x02U
66 /* 3rd Lock byte position after reading the block number 0x28 */
67 #define TYPE_2_LOCK_BYTE3_POS_RD_BLK28 0x00U
69 #ifdef PH_NDEF_MIFARE_ULC
71 /* Lock control TLVs, TYPE identifier */
72 #define LOCK_CTRL_TYPE_IN_TLV 0x01U
73 /* Lock control TLVs, Length expected */
74 #define LOCK_CTRL_LEN_IN_TLV 0x03U
76 /* NDEF message TLVs, TYPE identifier */
77 #define NDEF_TYPE_IN_TLV 0x03U
79 #define MFUL_NULL_TLV 0x00U
80 #define THREE_BYTE_LENGTH_FIELD 0xFFU
81 #define TERMINATOR_TLV 0xFEU
82 #define MIFARE_ULC_SIZE 0xC0U
83 #define MFUL_NIBBLE_SIZE 0x04U
84 #define MFUL_NIBBLE_MASK 0x0FU
85 #define MFUL_BYTE_SIZE_IN_BITS 0x08U
86 #define MFUL_BLOCK_SIZE_IN_BYTES 0x04U
87 /* Initial (0 to 3 blocks) 4 blocks are ignored, i.e., 16 bytes */
88 #define MFUL_INITIAL_BYTES_IGNORED 0x10U
90 #define MFUL_CONVERT_BITS_TO_BYTES(bits_to_bytes) \
91 (((bits_to_bytes % MFUL_BYTE_SIZE_IN_BITS) > 0) ? \
92 ((bits_to_bytes / MFUL_BYTE_SIZE_IN_BITS) + 1) : \
93 (bits_to_bytes / MFUL_BYTE_SIZE_IN_BITS))
95 typedef enum phFriNfc_MfUL_Parse
103 }phFriNfc_MfUL_Parse_t;
105 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
107 #endif /* #ifdef FRINFC_READONLY_NDEF */
109 * \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the
110 * transceive function
112 static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
115 * \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the
116 * read or write operation
118 static NFCSTATUS phFriNfc_MfUL_H_WrRd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
121 * \brief \copydoc page_ovr Helper function for Mifare UL. This function fills the
122 * send buffer for transceive function
124 static void phFriNfc_MfUL_H_fillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
128 * \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process
131 static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
134 * \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process the
137 static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
139 #ifdef FRINFC_READONLY_NDEF
141 #ifdef PH_NDEF_MIFARE_ULC
145 phFriNfc_MfUL_ParseTLVs (
146 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
147 uint8_t *data_to_parse,
148 uint8_t size_to_parse);
152 phFriNfc_MfUL_GetLockBytesInfo (
153 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
157 phFriNfc_MfUL_GetDefaultLockBytesInfo (
158 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
162 phFriNfc_MfUL_GetSkipSize (
163 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
164 uint8_t block_number,
165 uint8_t byte_number);
169 phFriNfc_MfUL_ReadWriteLockBytes (
170 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
174 phFriNfc_MfUL_UpdateAndWriteLockBits (
175 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
179 phFriNfc_MfUL_CalcRemainingLockBits (
180 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
182 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
184 #endif /* #ifdef FRINFC_READONLY_NDEF */
186 static int MemCompare1 ( void *s1, void *s2, unsigned int n );
187 /*The function does a comparision of two strings and returns a non zero value
188 if two strings are unequal*/
189 static int MemCompare1 ( void *s1, void *s2, unsigned int n )
192 int8_t *char_1 =(int8_t *)s1;
193 int8_t *char_2 =(int8_t *)s2;
194 if(NULL == s1 || NULL == s2)
196 PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare");
200 for(;((n>0)&&(diff==0));n--,char_1++,char_2++)
202 diff = *char_1 - *char_2;
208 void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
210 uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
212 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
213 (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
215 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
216 #ifdef FRINFC_READONLY_NDEF
217 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[0] = 0;
218 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[1] = 0;
219 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = 0;
220 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = 0;
221 #endif /* #ifdef FRINFC_READONLY_NDEF */
224 NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
226 NFCSTATUS Result = NFCSTATUS_SUCCESS;
227 uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
229 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
230 (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
232 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
235 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RD_16BYTES;
236 /* Initialise current block to the lock bits block */
237 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_2;
239 /* Start authentication */
240 Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
244 #ifdef FRINFC_READONLY_NDEF
247 phFriNfc_MfUL_ConvertToReadOnly (
248 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
250 NFCSTATUS result = NFCSTATUS_SUCCESS;
252 NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = TRUE;
253 NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0;
255 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_16BYTES;
257 result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
262 #endif /* #ifdef FRINFC_READONLY_NDEF */
264 void phFriNfc_MfUL_Process(void *Context,
267 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
269 if(Status == NFCSTATUS_SUCCESS)
271 switch(NdefSmtCrdFmt->State)
273 case PH_FRINFC_MFUL_FMT_RD_16BYTES:
274 Status = phFriNfc_MfUL_H_ProRd16Bytes(NdefSmtCrdFmt);
277 case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
278 Status = phFriNfc_MfUL_H_ProWrOTPBytes(NdefSmtCrdFmt);
281 case PH_FRINFC_MFUL_FMT_WR_TLV:
282 #ifdef PH_NDEF_MIFARE_ULC
283 if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
285 /* Write NDEF TLV in block number 5 */
286 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
287 PH_FRINFC_MFUL_FMT_VAL_5;
288 /* Card already have the OTP bytes so write TLV */
289 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV1;
291 Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
293 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
297 #ifdef FRINFC_READONLY_NDEF
299 case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES:
301 if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
303 uint8_t otp_lock_page_size = 0;
306 otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes);
307 (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes,
308 (void *)NdefSmtCrdFmt->SendRecvBuf,
309 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes));
311 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = (uint8_t)
312 (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2]
313 | MIFARE_UL_LOCK_BYTE1_VALUE);
314 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = MIFARE_UL_LOCK_BYTE2_VALUE;
315 i = (uint8_t)(i + otp_lock_page_size);
317 otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes);
319 (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
320 (void *)(NdefSmtCrdFmt->SendRecvBuf + i),
321 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
323 NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[(otp_lock_page_size - 1)] =
324 READ_ONLY_VALUE_IN_OTP;
326 switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION])
328 case TYPE_2_STATIC_MEM_SIZE_VALUE:
330 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES;
331 Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
335 #ifdef PH_NDEF_MIFARE_ULC
336 case TYPE_2_DYNAMIC_MEM_SIZE_VALUE:
338 NdefSmtCrdFmt->State =
339 PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES;
341 /* Start reading from block 4 */
342 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 4;
343 Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
346 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
350 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
351 NFCSTATUS_INVALID_DEVICE_REQUEST);
358 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
359 NFCSTATUS_INVALID_RECEIVE_LENGTH);
364 case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES:
366 switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION])
368 case TYPE_2_STATIC_MEM_SIZE_VALUE:
369 #ifdef PH_NDEF_MIFARE_ULC
370 case TYPE_2_DYNAMIC_MEM_SIZE_VALUE:
371 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
373 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES;
374 Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
380 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
381 NFCSTATUS_INVALID_DEVICE_REQUEST);
388 #ifdef PH_NDEF_MIFARE_ULC
390 case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES:
392 if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
394 Status = phFriNfc_MfUL_ParseTLVs (NdefSmtCrdFmt,
395 NdefSmtCrdFmt->SendRecvBuf,
396 (uint8_t)*NdefSmtCrdFmt->SendRecvLength);
400 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
401 NdefSmtCrdFmt->AddInfo.Type2Info.LockBlockNumber;
402 Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt);
407 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
408 NFCSTATUS_INVALID_RECEIVE_LENGTH);
413 case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES:
415 if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
417 (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.ReadData,
418 (void *)NdefSmtCrdFmt->SendRecvBuf,
419 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.ReadData));
421 NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0;
423 Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt);
428 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
429 NFCSTATUS_INVALID_RECEIVE_LENGTH);
434 case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES:
436 NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = (uint8_t)
437 (NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex +
438 MFUL_BLOCK_SIZE_IN_BYTES);
440 if (!phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt))
442 /* There is no lock bits to write, then write OTP bytes */
443 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES;
444 Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
446 else if ((NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex <
447 MIFARE_UL_READ_MAX_SIZE)
448 && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)))
450 /* If remaining lock bits has to be written and the data is already read */
451 Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt);
455 /* Increment current block by 4 because if a data is read then 16
456 bytes will be given which is 4 blocks */
457 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = (uint8_t)
458 (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4);
459 Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt);
464 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
466 case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES:
472 #endif /* #ifdef FRINFC_READONLY_NDEF */
474 #ifdef PH_NDEF_MIFARE_ULC
475 case PH_FRINFC_MFUL_FMT_WR_TLV1:
478 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
481 Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
482 NFCSTATUS_INVALID_DEVICE_REQUEST);
486 /* Status is not success then call completion routine */
487 if(Status != NFCSTATUS_PENDING)
489 phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status);
493 #ifdef FRINFC_READONLY_NDEF
495 #ifdef PH_NDEF_MIFARE_ULC
499 phFriNfc_MfUL_GetSkipSize (
500 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
501 uint8_t block_number,
504 uint8_t skip_size = 0;
505 phFriNfc_Type2_AddInfo_t *ps_type2_info =
506 &NdefSmtCrdFmt->AddInfo.Type2Info;
508 /* This check is added, because the default lock bits is always
509 present after the DATA AREA.
510 So, default lock bytes doesnt have any skip size */
511 if (!ps_type2_info->DefaultLockBytesFlag)
513 /* Only check for the lock control TLV */
514 if ((block_number == ps_type2_info->LockBlockNumber)
515 && (byte_number == ps_type2_info->LockByteNumber))
517 skip_size = MFUL_CONVERT_BITS_TO_BYTES(ps_type2_info->NoOfLockBits);
526 phFriNfc_MfUL_GetLockBytesInfo (
527 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
529 NFCSTATUS result = NFCSTATUS_SUCCESS;
530 phFriNfc_Type2_AddInfo_t *ps_type2_info =
531 &(NdefSmtCrdFmt->AddInfo.Type2Info);
532 uint8_t page_address = 0;
533 uint8_t bytes_offset = 0;
534 uint8_t lock_index = 0;
537 page_address = (uint8_t)(ps_type2_info->DynLockBytes[lock_index] >> MFUL_NIBBLE_SIZE);
538 bytes_offset = (uint8_t)(ps_type2_info->DynLockBytes[lock_index] & MFUL_NIBBLE_MASK);
540 lock_index = (lock_index + 1);
541 ps_type2_info->NoOfLockBits = ps_type2_info->DynLockBytes[lock_index];
543 lock_index = (lock_index + 1);
544 ps_type2_info->LockBytesPerPage =
545 (ps_type2_info->DynLockBytes[lock_index] & MFUL_NIBBLE_MASK);
546 ps_type2_info->BytesLockedPerLockBit =
547 (ps_type2_info->DynLockBytes[lock_index] >> MFUL_NIBBLE_SIZE);
549 /* Apply the formula to calculate byte address
550 ByteAddr = ((PageAddr * (2 ^ BytesPerPage)) + ByteOffset)
552 ps_type2_info->LockByteNumber = (uint8_t)((page_address
553 * (1 << ps_type2_info->LockBytesPerPage))
556 ps_type2_info->LockBlockNumber = (uint8_t)(ps_type2_info->LockByteNumber /
557 MFUL_BLOCK_SIZE_IN_BYTES);
558 ps_type2_info->LockByteNumber = (uint8_t)(ps_type2_info->LockByteNumber %
559 MFUL_BLOCK_SIZE_IN_BYTES);
563 /* Out of bound memory check */
564 ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) >
565 (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] *
566 TOPAZ_BYTES_PER_BLOCK)) ||
568 /* Check the static lock and reserved areas memory blocks */
569 ((ps_locktlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) &&
570 (ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) ||
571 (((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) >=
572 TOPAZ_STATIC_LOCK_RES_START) &&
573 ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) <
574 TOPAZ_STATIC_LOCK_RES_END))
577 ps_locktlv_info->ByteAddr = 0;
578 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
579 NFCSTATUS_NO_NDEF_SUPPORT);
583 ps_locktlv_info->BlkNum = (ps_locktlv_info->ByteAddr /
584 TOPAZ_BYTES_PER_BLOCK);
585 ps_locktlv_info->ByteNum = (ps_locktlv_info->ByteAddr %
586 TOPAZ_BYTES_PER_BLOCK);
595 phFriNfc_MfUL_CalcRemainingLockBits (
596 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
598 uint8_t lock_bits_remaining = 0;
599 phFriNfc_Type2_AddInfo_t *ps_type2_info =
600 &(NdefSmtCrdFmt->AddInfo.Type2Info);
602 lock_bits_remaining = (uint8_t)(ps_type2_info->NoOfLockBits -
603 ps_type2_info->LockBitsWritten);
605 return lock_bits_remaining;
610 phFriNfc_MfUL_UpdateAndWriteLockBits (
611 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
613 NFCSTATUS result = NFCSTATUS_SUCCESS;
614 phFriNfc_Type2_AddInfo_t *ps_type2_info =
615 &(NdefSmtCrdFmt->AddInfo.Type2Info);
616 uint8_t byte_index = 0;
617 uint8_t no_of_bits_left_in_block = 0;
618 uint8_t remaining_lock_bits = 0;
619 uint8_t remaining_lock_bytes = 0;
620 /* Array of 3 is used because the lock bits with 4 bytes in a block
621 is handled in the function phFriNfc_MfUL_ReadWriteLockBytes
622 So use this function only if lock bytes doesnt use the entire block */
623 uint8_t lock_bytes_value[MFUL_BLOCK_SIZE_IN_BYTES] = {0};
624 uint8_t lock_byte_index = 0;
626 (void)memcpy ((void *)lock_bytes_value,
627 (void*)(ps_type2_info->ReadData + ps_type2_info->ReadDataIndex),
628 sizeof (ps_type2_info->DynLockBytes));
629 remaining_lock_bits = phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt);
631 if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber)
633 /* 1st write to lock bits, so byte_index is updated */
634 byte_index = ps_type2_info->LockByteNumber;
637 no_of_bits_left_in_block = (uint8_t)((MFUL_BLOCK_SIZE_IN_BYTES - byte_index) *
638 MFUL_BYTE_SIZE_IN_BITS);
640 if (no_of_bits_left_in_block >= remaining_lock_bits)
642 /* Entire lock bits can be written
643 if block size is more than number of lock bits.
644 so allocate the lock bits with value 1b and
645 dont change the remaining bits */
646 if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS)
648 /* mod operation has resulted in a value, means lock bits ends in between a byte */
649 uint8_t mod_value = 0;
651 remaining_lock_bytes = ((remaining_lock_bits /
652 MFUL_BYTE_SIZE_IN_BITS) + 1);
654 /* mod_value is used to fill the only partial bits and
655 remaining bits shall be untouched */
656 mod_value = (uint8_t)(remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS);
657 if (remaining_lock_bits > MFUL_BYTE_SIZE_IN_BITS)
659 /* lock bits to write is greater than 8 bits */
660 while (lock_byte_index < (remaining_lock_bytes - 1))
662 /* Set 1b to all bits left in the block */
663 lock_bytes_value[byte_index] = 0xFF;
664 lock_byte_index = (uint8_t)(lock_byte_index + 1);
665 byte_index = (uint8_t)(byte_index + 1);
667 /* Last byte of the lock bits shall be filled partially,
668 Set only the remaining lock bits and dont change
669 the other bit value */
670 lock_bytes_value[byte_index] = 0;
671 lock_bytes_value[byte_index] = (uint8_t)
672 SET_BITS8 (lock_bytes_value[byte_index], 0,
677 /* lock bits to write is less than 8 bits, so
678 there is only one byte to write.
679 Set only the remaining lock bits and dont change
680 the other bit value */
681 lock_bytes_value[0] = (uint8_t)SET_BITS8 (lock_bytes_value[0], 0,
684 } /* if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */
687 /* MOD operation is 00, that means entire byte value shall be 0xFF, means
688 every bit shall be to 1 */
689 remaining_lock_bytes = (remaining_lock_bits /
690 MFUL_BYTE_SIZE_IN_BITS);
692 while (lock_byte_index < remaining_lock_bytes)
694 /* Set 1b to all bits left in the block */
695 lock_bytes_value[byte_index] = 0xFF;
696 lock_byte_index = (uint8_t)(lock_byte_index + 1);
697 byte_index = (uint8_t)(byte_index + 1);
699 } /* else of if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */
700 ps_type2_info->LockBitsWritten = (uint8_t)(ps_type2_info->LockBitsWritten +
701 remaining_lock_bits);
702 } /* if (no_of_bits_left_in_block >= remaining_lock_bits) */
705 /* Update till the left bits in the block and then carry
706 out next operation after this write */
707 while (lock_byte_index < (no_of_bits_left_in_block / MFUL_BYTE_SIZE_IN_BITS))
709 /* Set 1b to all bits left in the block */
710 lock_bytes_value[byte_index] = 0xFF;
711 lock_byte_index = (uint8_t)(lock_byte_index + 1);
712 byte_index = (uint8_t)(byte_index + 1);
714 ps_type2_info->LockBitsWritten = (uint8_t)(ps_type2_info->LockBitsWritten +
715 no_of_bits_left_in_block);
716 } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */
719 /* Copy the values back to the DynLockBytes structure member */
720 (void)memcpy ((void*)ps_type2_info->DynLockBytes,
721 (void *)lock_bytes_value,
722 sizeof (ps_type2_info->DynLockBytes));
725 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES;
726 result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
733 phFriNfc_MfUL_ReadWriteLockBytes (
734 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
736 NFCSTATUS result = NFCSTATUS_SUCCESS;
737 phFriNfc_Type2_AddInfo_t *ps_type2_info =
738 &(NdefSmtCrdFmt->AddInfo.Type2Info);
739 uint8_t write_flag = FALSE;
741 if (/* Lock bytes starts from the beginning of the block */
742 (0 == ps_type2_info->LockByteNumber)
743 /* To make sure this is the first read */
744 && (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber)
745 /* Lock bytes are greater than or equal to the block size, i.e., 4 bytes */
746 && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)
747 >= (MFUL_BLOCK_SIZE_IN_BYTES * MFUL_BYTE_SIZE_IN_BITS)))
749 /* Then directly write the lock bytes, dont waste time for read */
750 (void)memset ((void *)ps_type2_info->DynLockBytes, 0xFF,
751 sizeof (ps_type2_info->DynLockBytes));
754 else if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber)
756 /* Read is mandatory, First read and then update the block,
757 because chances are there that lock byte may start in between
760 else if (/* check if remaining bytes exceeds or same as the block size */
761 (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)
762 >= (MFUL_BLOCK_SIZE_IN_BYTES * MFUL_BYTE_SIZE_IN_BITS)))
764 /* Then directly write the lock bytes, dont waste time for read */
765 (void)memset ((void *)ps_type2_info->DynLockBytes, 0xFF,
766 sizeof (ps_type2_info->DynLockBytes));
771 /* Read is mandatory, First read and then update the block */
776 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES;
777 result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
781 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES;
782 result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
790 phFriNfc_MfUL_GetDefaultLockBytesInfo (
791 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
793 NFCSTATUS result = NFCSTATUS_SUCCESS;
794 phFriNfc_Type2_AddInfo_t *ps_type2_info =
795 &(NdefSmtCrdFmt->AddInfo.Type2Info);
796 uint16_t lock_byte_start_addr = 0;
798 /* The position of the dynamic lock bits starts from
799 the first byte after the data area */
800 lock_byte_start_addr = (uint16_t)(MFUL_INITIAL_BYTES_IGNORED +
801 (ps_type2_info->OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8));
803 ps_type2_info->LockBlockNumber = (uint8_t)(lock_byte_start_addr /
804 MFUL_BLOCK_SIZE_IN_BYTES);
805 ps_type2_info->LockByteNumber = (uint8_t)(lock_byte_start_addr %
806 MFUL_BLOCK_SIZE_IN_BYTES);
808 NoOfLockBits = [(DataAreaSize - 48)/8] */
809 ps_type2_info->NoOfLockBits = (uint8_t)
810 (((ps_type2_info->OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8) - 48)/8);
817 phFriNfc_MfUL_ParseTLVs (
818 phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
819 uint8_t *data_to_parse,
820 uint8_t size_to_parse)
822 NFCSTATUS result = NFCSTATUS_SUCCESS;
823 static uint8_t lock_mem_ndef_index = 0;
824 static uint8_t skip_lock_mem_size = 0;
825 static uint16_t card_size_remaining = 0;
826 static uint16_t ndef_data_size = 0;
827 static phFriNfc_MfUL_Parse_t parse_tlv = LOCK_TLV_T;
828 uint8_t parse_index = 0;
830 if ((0 == card_size_remaining) && (0 == parse_index))
832 /* card size is calculated only once */
833 card_size_remaining = (uint16_t)
834 (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8);
837 while ((parse_index < size_to_parse)
838 && (NFCSTATUS_SUCCESS == result)
839 && (NDEF_TLV_V != parse_tlv)
840 && (0 != card_size_remaining))
842 if (0 == skip_lock_mem_size)
844 /* Skip the lock TLVs, so get the lock bits */
845 skip_lock_mem_size = phFriNfc_MfUL_GetSkipSize (NdefSmtCrdFmt,
846 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock,
850 if (0 != skip_lock_mem_size)
852 if (skip_lock_mem_size >= (size_to_parse - parse_index))
854 /* if skip size is more than the size to parse, then */
855 card_size_remaining = (uint16_t)(card_size_remaining -
856 (size_to_parse - parse_index));
857 skip_lock_mem_size = (uint8_t)(skip_lock_mem_size -
858 ((size_to_parse - parse_index)));
859 parse_index = size_to_parse;
863 card_size_remaining = (uint16_t)(card_size_remaining -
866 parse_index = (uint8_t)(parse_index + skip_lock_mem_size);
867 skip_lock_mem_size = 0;
876 switch (*(data_to_parse + parse_index))
880 /* Do nothing, parse further */
884 case LOCK_CTRL_TYPE_IN_TLV:
886 parse_tlv = LOCK_TLV_L;
890 case NDEF_TYPE_IN_TLV:
892 parse_tlv = NDEF_TLV_T;
893 /* Default lock bytes shall be taken */
894 NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag =
896 result = phFriNfc_MfUL_GetDefaultLockBytesInfo (NdefSmtCrdFmt);
902 parse_tlv = LOCK_TLV_T;
903 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
904 NFCSTATUS_NO_NDEF_SUPPORT);
913 if (LOCK_CTRL_LEN_IN_TLV == *(data_to_parse + parse_index))
915 parse_tlv = LOCK_TLV_V;
919 skip_lock_mem_size = 0;
920 parse_tlv = LOCK_TLV_T;
921 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
922 NFCSTATUS_NO_NDEF_SUPPORT);
929 switch (lock_mem_ndef_index)
934 NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag =
936 NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes[lock_mem_ndef_index] =
937 *(data_to_parse + parse_index);
938 lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
944 NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes[lock_mem_ndef_index] =
945 *(data_to_parse + parse_index);
946 parse_tlv = NDEF_TLV_T;
947 lock_mem_ndef_index = 0;
948 result = phFriNfc_MfUL_GetLockBytesInfo (NdefSmtCrdFmt);
954 skip_lock_mem_size = 0;
955 parse_tlv = LOCK_TLV_T;
956 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
957 NFCSTATUS_NO_NDEF_SUPPORT);
962 } /* switch (lock_mem_ndef_index) in case LOCK_TLV_V */
966 switch (*(data_to_parse + parse_index))
970 /* Do nothing, parse further */
974 case NDEF_TYPE_IN_TLV:
976 parse_tlv = NDEF_TLV_L;
982 skip_lock_mem_size = 0;
983 parse_tlv = LOCK_TLV_T;
984 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
985 NFCSTATUS_NO_NDEF_SUPPORT);
990 } /* switch (*(data_to_parse + parse_index)) in case NDEF_TLV_T */
994 switch (lock_mem_ndef_index)
998 if (THREE_BYTE_LENGTH_FIELD == *(data_to_parse + parse_index))
1000 lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
1004 ndef_data_size = *(data_to_parse + parse_index);
1005 parse_tlv = NDEF_TLV_V;
1006 lock_mem_ndef_index = 0;
1013 ndef_data_size = (uint16_t)(*(data_to_parse + parse_index) << 8);
1019 ndef_data_size = (uint16_t)(ndef_data_size |
1020 *(data_to_parse + parse_index));
1021 parse_tlv = NDEF_TLV_V;
1022 lock_mem_ndef_index = 0;
1025 } /* switch (lock_mem_ndef_index) in case NDEF_TLV_L */
1036 skip_lock_mem_size = 0;
1037 parse_tlv = LOCK_TLV_T;
1038 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
1039 NFCSTATUS_NO_NDEF_SUPPORT);
1042 } /* switch (parse_tlv) */
1044 } /* else part of if (0 != skip_lock_mem_size) */
1046 if (0 == card_size_remaining)
1048 skip_lock_mem_size = 0;
1049 parse_tlv = LOCK_TLV_T;
1050 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
1051 NFCSTATUS_NO_NDEF_SUPPORT);
1053 else if (NDEF_TLV_V != parse_tlv)
1055 /* Increment the index */
1056 parse_index = (uint8_t)(parse_index + 1);
1057 /* card size is decremented as the memory area is parsed */
1058 card_size_remaining = (uint16_t)(card_size_remaining - 1);
1062 /* L field of the NDEF TLV
1063 L field can have 1 byte or also 3 bytes
1065 uint8_t length_to_deduct = 1;
1067 if ((NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION]
1068 * 8) >= THREE_BYTE_LENGTH_FIELD)
1070 length_to_deduct = 3;
1072 /* parse_tlv has reached the VALUE field of the NDEF TLV */
1073 if ((card_size_remaining - length_to_deduct) < ndef_data_size)
1075 result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
1076 NFCSTATUS_NO_NDEF_SUPPORT);
1079 lock_mem_ndef_index = 0;
1080 skip_lock_mem_size = 0;
1081 card_size_remaining = 0;
1083 } /* while ((parse_index < size_to_parse)
1084 && (NFCSTATUS_SUCCESS != result)
1085 && (NDEF_TLV_V != parse_tlv)
1086 && (0 != card_size_remaining)) */
1088 if ((NDEF_TLV_V == parse_tlv) || (NFCSTATUS_SUCCESS != result))
1090 parse_tlv = LOCK_TLV_T;
1094 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES;
1095 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
1096 (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4);
1098 result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
1101 if (NFCSTATUS_PENDING != result)
1103 lock_mem_ndef_index = 0;
1104 skip_lock_mem_size = 0;
1105 card_size_remaining = 0;
1110 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1112 #endif /* #ifdef FRINFC_READONLY_NDEF */
1114 static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
1116 NFCSTATUS Result = NFCSTATUS_SUCCESS;
1118 /* Fill the send buffer */
1119 phFriNfc_MfUL_H_fillSendBuf(NdefSmtCrdFmt,
1120 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock);
1122 /* Call transceive */
1123 Result = phFriNfc_MfUL_H_Transceive (NdefSmtCrdFmt);
1128 static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt)
1130 NFCSTATUS Result = NFCSTATUS_SUCCESS;
1132 /* set the data for additional data exchange*/
1133 NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
1134 NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0;
1135 NdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0;
1137 /*set the completion routines for the card operations*/
1138 NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process;
1139 NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt;
1141 *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;
1143 /* Call the Overlapped HAL Transceive function */
1144 Result = phFriNfc_OvrHal_Transceive( NdefSmtCrdFmt->LowerDevice,
1145 &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
1146 NdefSmtCrdFmt->psRemoteDevInfo,
1148 &NdefSmtCrdFmt->psDepAdditionalInfo,
1149 NdefSmtCrdFmt->SendRecvBuf,
1150 NdefSmtCrdFmt->SendLength,
1151 NdefSmtCrdFmt->SendRecvBuf,
1152 NdefSmtCrdFmt->SendRecvLength);
1156 static void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
1159 #ifdef PH_NDEF_MIFARE_ULC
1160 uint8_t NDEFTLV1[4] = {0x01, 0x03, 0xA0, 0x10};
1161 uint8_t NDEFTLV2[4] = {0x44, 0x03, 0x00, 0xFE};
1162 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1163 uint8_t NDEFTLV[4] = {0x03, 0x00, 0xFE, 0x00};
1168 /* First byte for send buffer is always the block number */
1169 NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_0] = (uint8_t)BlockNo;
1170 switch(NdefSmtCrdFmt->State)
1172 #ifdef FRINFC_READONLY_NDEF
1174 case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES:
1176 #ifdef PH_HAL4_ENABLE
1177 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1180 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
1181 #endif /* #ifdef PH_HAL4_ENABLE */
1182 *NdefSmtCrdFmt->SendRecvBuf = RD_LOCK_OTP_BLOCK_NUMBER;
1183 /* Send length for read command is always one */
1184 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
1188 #ifdef PH_NDEF_MIFARE_ULC
1190 case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES:
1192 #ifdef PH_HAL4_ENABLE
1193 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1196 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
1197 #endif /* #ifdef PH_HAL4_ENABLE */
1198 *NdefSmtCrdFmt->SendRecvBuf =
1199 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock;
1200 /* Send length for read command is always one */
1201 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
1205 case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES:
1207 #ifdef PH_HAL4_ENABLE
1208 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1211 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
1212 #endif /* #ifdef PH_HAL4_ENABLE */
1213 *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock;
1214 /* Send length for read command is always one */
1215 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
1219 case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES:
1221 #ifdef PH_HAL4_ENABLE
1222 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1225 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1226 #endif /* #ifdef PH_HAL4_ENABLE */
1228 /* Send length for read command is always one */
1229 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1230 *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock;
1231 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1232 NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes,
1233 PH_FRINFC_MFUL_FMT_VAL_4);
1237 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1239 case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES:
1241 #ifdef PH_HAL4_ENABLE
1242 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1245 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1246 #endif /* #ifdef PH_HAL4_ENABLE */
1248 /* Send length for read command is always one */
1249 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1250 *NdefSmtCrdFmt->SendRecvBuf = RD_LOCK_OTP_BLOCK_NUMBER;
1251 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1252 NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes,
1253 PH_FRINFC_MFUL_FMT_VAL_4);
1257 case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES:
1259 #ifdef PH_HAL4_ENABLE
1260 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1263 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1264 #endif /* #ifdef PH_HAL4_ENABLE */
1266 /* Send length for read command is always one */
1267 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1268 *NdefSmtCrdFmt->SendRecvBuf = OTP_BLOCK_NUMBER;
1269 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1270 NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1271 PH_FRINFC_MFUL_FMT_VAL_4);
1275 #endif /* #ifdef FRINFC_READONLY_NDEF */
1277 case PH_FRINFC_MFUL_FMT_RD_16BYTES:
1278 #ifdef PH_HAL4_ENABLE
1279 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1282 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead;
1283 #endif /* #ifdef PH_HAL4_ENABLE */
1284 /* Send length for read command is always one */
1285 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1;
1288 case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
1289 /* Send length for read command is always Five */
1290 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1292 #ifdef PH_HAL4_ENABLE
1293 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1295 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1296 #endif /* #ifdef PH_HAL4_ENABLE */
1297 /* Copy the OTP bytes */
1298 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1299 NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1300 PH_FRINFC_MFUL_FMT_VAL_4);
1303 case PH_FRINFC_MFUL_FMT_WR_TLV:
1304 #ifndef PH_NDEF_MIFARE_ULC
1306 #endif /* #ifndef PH_NDEF_MIFARE_ULC */
1307 /* Send length for read command is always Five */
1308 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1310 #ifdef PH_HAL4_ENABLE
1311 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1313 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1314 #endif /* #ifdef PH_HAL4_ENABLE */
1315 /* Copy the NDEF TLV */
1316 #ifdef PH_NDEF_MIFARE_ULC
1318 if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
1320 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1322 PH_FRINFC_MFUL_FMT_VAL_4);
1324 else if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD)
1326 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1328 PH_FRINFC_MFUL_FMT_VAL_4);
1334 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1336 PH_FRINFC_MFUL_FMT_VAL_4);
1338 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1342 #ifdef PH_NDEF_MIFARE_ULC
1343 case PH_FRINFC_MFUL_FMT_WR_TLV1:
1344 if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
1346 /* Send length for write command is always Five */
1347 NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1349 NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1350 (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1352 PH_FRINFC_MFUL_FMT_VAL_4);
1357 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1363 static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
1365 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
1366 NFCSTATUS_FORMAT_ERROR);
1367 uint32_t memcompare = PH_FRINFC_MFUL_FMT_VAL_0;
1368 uint8_t ZeroBuf[] = {0x00, 0x00, 0x00, 0x00};
1370 #ifdef PH_NDEF_MIFARE_ULC
1371 uint8_t OTPByteUL[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
1372 uint8_t OTPByteULC[] = PH_FRINFC_MFULC_FMT_OTP_BYTES;
1373 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1375 /* Check the lock bits (byte number 2 and 3 of block number 2) */
1376 if ((NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_2] ==
1377 PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL) &&
1378 (NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_3] ==
1379 PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL))
1382 #ifdef PH_NDEF_MIFARE_ULC
1384 if (NdefSmtCrdFmt->SendRecvBuf[8] == 0x02 &&
1385 NdefSmtCrdFmt->SendRecvBuf[9] == 0x00)
1387 NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD;
1389 (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1391 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
1393 else if (NdefSmtCrdFmt->SendRecvBuf[8] == 0xFF &&
1394 NdefSmtCrdFmt->SendRecvBuf[9] == 0xFF)
1396 NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
1398 (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1400 sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
1404 NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
1407 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1409 memcompare = (uint32_t)
1410 MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
1411 NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1412 PH_FRINFC_MFUL_FMT_VAL_4);
1414 if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
1416 /* Write NDEF TLV in block number 4 */
1417 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
1418 PH_FRINFC_MFUL_FMT_VAL_4;
1419 /* Card already have the OTP bytes so write TLV */
1420 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
1424 /* IS the card new, OTP bytes = {0x00, 0x00, 0x00, 0x00} */
1425 memcompare = (uint32_t)MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
1427 PH_FRINFC_MFUL_FMT_VAL_4);
1428 /* If OTP bytes are Zero then the card is Zero */
1429 if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
1431 /* Write OTP bytes in block number 3 */
1432 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
1433 PH_FRINFC_MFUL_FMT_VAL_3;
1434 /* Card already have the OTP bytes so write TLV */
1435 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_OTPBYTES;
1442 #ifdef PH_NDEF_MIFARE_ULC
1444 ((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) ||
1445 (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES)) &&
1446 ((NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) ||
1447 (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD))
1450 if((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) ||
1451 (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES))
1452 #endif /* #ifdef PH_NDEF_MIFARE_ULC */
1454 Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
1459 static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
1461 NFCSTATUS Result = NFCSTATUS_SUCCESS;
1462 /* Card already have the OTP bytes so write TLV */
1463 NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
1465 /* Write NDEF TLV in block number 4 */
1466 NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
1467 PH_FRINFC_MFUL_FMT_VAL_4;
1469 Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);