1/*
2 * Copyright (C) 2010 NXP Semiconductors
3 *
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
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/*
18 * \file  phFriNfc_MifULFormat.c
19 * \brief NFC Ndef Formatting For Mifare ultralight card.
20 *
21 * Project: NFC-FRI
22 *
23 * $Date: Mon Dec 13 14:14:12 2010 $
24 * $Author: ing02260 $
25 * $Revision: 1.9 $
26 * $Aliases:  $
27 *
28 */
29
30#include <phFriNfc_MifULFormat.h>
31#include <phFriNfc_OvrHal.h>
32
33/*! \ingroup grp_file_attributes
34 *  \name NDEF Mapping
35 *
36 * File: \ref phFriNfc_MifULFormat.c
37 *
38 */
39/*@{*/
40#define PHFRINFCMIFULFORMAT_FILEREVISION "$Revision: 1.9 $"
41#define PHFRINFCMIFULFORMAT_FILEALIASES  "$Aliases:  $"
42/*@}*/
43
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
68
69#ifdef PH_NDEF_MIFARE_ULC
70
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
75
76    /* NDEF message TLVs, TYPE identifier */
77    #define NDEF_TYPE_IN_TLV                    0x03U
78
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
89
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))
94
95    typedef enum phFriNfc_MfUL_Parse
96    {
97        LOCK_TLV_T,
98        LOCK_TLV_L,
99        LOCK_TLV_V,
100        NDEF_TLV_T,
101        NDEF_TLV_L,
102        NDEF_TLV_V
103    }phFriNfc_MfUL_Parse_t;
104
105#endif /* #ifdef PH_NDEF_MIFARE_ULC */
106
107#endif /* #ifdef FRINFC_READONLY_NDEF */
108/*!
109* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the
110* transceive function
111*/
112static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt);
113
114/*!
115* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the
116* read or write operation
117*/
118static NFCSTATUS phFriNfc_MfUL_H_WrRd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
119
120/*!
121* \brief \copydoc page_ovr Helper function for Mifare UL. This function fills the
122* send buffer for transceive function
123*/
124static void phFriNfc_MfUL_H_fillSendBuf(phFriNfc_sNdefSmtCrdFmt_t   *NdefSmtCrdFmt,
125                                        uint8_t                     BlockNo);
126
127/*!
128* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process
129* the read bytes
130*/
131static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt);
132
133/*!
134* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process the
135* OTP bytes written
136*/
137static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt);
138
139#ifdef FRINFC_READONLY_NDEF
140
141#ifdef PH_NDEF_MIFARE_ULC
142
143static
144NFCSTATUS
145phFriNfc_MfUL_ParseTLVs (
146    phFriNfc_sNdefSmtCrdFmt_t       *NdefSmtCrdFmt,
147    uint8_t                         *data_to_parse,
148    uint8_t                         size_to_parse);
149
150static
151NFCSTATUS
152phFriNfc_MfUL_GetLockBytesInfo (
153    phFriNfc_sNdefSmtCrdFmt_t       *NdefSmtCrdFmt);
154
155static
156NFCSTATUS
157phFriNfc_MfUL_GetDefaultLockBytesInfo (
158    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt);
159
160static
161uint8_t
162phFriNfc_MfUL_GetSkipSize (
163    phFriNfc_sNdefSmtCrdFmt_t       *NdefSmtCrdFmt,
164    uint8_t                         block_number,
165    uint8_t                         byte_number);
166
167static
168NFCSTATUS
169phFriNfc_MfUL_ReadWriteLockBytes (
170    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt);
171
172static
173NFCSTATUS
174phFriNfc_MfUL_UpdateAndWriteLockBits (
175    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt);
176
177static
178uint8_t
179phFriNfc_MfUL_CalcRemainingLockBits (
180    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt);
181
182#endif /* #ifdef PH_NDEF_MIFARE_ULC */
183
184#endif /* #ifdef FRINFC_READONLY_NDEF */
185
186static int MemCompare1 ( void *s1, void *s2, unsigned int n );
187/*The function does a comparision of two strings and returns a non zero value
188if two strings are unequal*/
189static int MemCompare1 ( void *s1, void *s2, unsigned int n )
190{
191    int8_t   diff = 0;
192    int8_t *char_1  =(int8_t *)s1;
193    int8_t *char_2  =(int8_t *)s2;
194    if(NULL == s1 || NULL == s2)
195    {
196        PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare");
197    }
198    else
199    {
200        for(;((n>0)&&(diff==0));n--,char_1++,char_2++)
201        {
202            diff = *char_1 - *char_2;
203        }
204    }
205    return (int)diff;
206}
207
208void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
209{
210    uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
211
212    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
213    (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
214                OTPByte,
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 */
222}
223
224NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
225{
226    NFCSTATUS               Result = NFCSTATUS_SUCCESS;
227    uint8_t                 OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES;
228
229    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0;
230    (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
231                OTPByte,
232                sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
233
234    /* Set the state */
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;
238
239    /* Start authentication */
240    Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
241    return Result;
242}
243
244#ifdef FRINFC_READONLY_NDEF
245
246NFCSTATUS
247phFriNfc_MfUL_ConvertToReadOnly (
248    phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
249{
250    NFCSTATUS               result = NFCSTATUS_SUCCESS;
251
252    NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = TRUE;
253    NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0;
254
255    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_16BYTES;
256
257    result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
258
259    return result;
260}
261
262#endif /* #ifdef FRINFC_READONLY_NDEF */
263
264void phFriNfc_MfUL_Process(void             *Context,
265                           NFCSTATUS        Status)
266{
267    phFriNfc_sNdefSmtCrdFmt_t  *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context;
268
269    if(Status == NFCSTATUS_SUCCESS)
270    {
271        switch(NdefSmtCrdFmt->State)
272        {
273        case PH_FRINFC_MFUL_FMT_RD_16BYTES:
274            Status = phFriNfc_MfUL_H_ProRd16Bytes(NdefSmtCrdFmt);
275            break;
276
277        case PH_FRINFC_MFUL_FMT_WR_OTPBYTES:
278            Status = phFriNfc_MfUL_H_ProWrOTPBytes(NdefSmtCrdFmt);
279            break;
280
281        case PH_FRINFC_MFUL_FMT_WR_TLV:
282#ifdef PH_NDEF_MIFARE_ULC
283            if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
284            {
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;
290
291                Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
292            }
293#endif /* #ifdef PH_NDEF_MIFARE_ULC */
294
295            break;
296
297#ifdef FRINFC_READONLY_NDEF
298
299        case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES:
300        {
301            if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
302            {
303                uint8_t         otp_lock_page_size = 0;
304                uint8_t         i = 0;
305
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));
310
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);
316
317                otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes);
318
319                (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
320                            (void *)(NdefSmtCrdFmt->SendRecvBuf + i),
321                            sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
322
323                NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[(otp_lock_page_size - 1)] =
324                                                        READ_ONLY_VALUE_IN_OTP;
325
326                switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION])
327                {
328                    case TYPE_2_STATIC_MEM_SIZE_VALUE:
329                    {
330                        NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES;
331                        Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
332                        break;
333                    }
334
335#ifdef PH_NDEF_MIFARE_ULC
336                    case TYPE_2_DYNAMIC_MEM_SIZE_VALUE:
337                    {
338                        NdefSmtCrdFmt->State =
339                                PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES;
340
341                        /* Start reading from block 4 */
342                        NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 4;
343                        Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
344                        break;
345                    }
346#endif /* #ifdef PH_NDEF_MIFARE_ULC */
347
348                    default:
349                    {
350                        Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
351                                            NFCSTATUS_INVALID_DEVICE_REQUEST);
352                        break;
353                    }
354                }
355            }
356            else
357            {
358                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
359                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
360            }
361            break;
362        }
363
364        case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES:
365        {
366            switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION])
367            {
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 */
372                {
373                    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES;
374                    Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
375                    break;
376                }
377
378                default:
379                {
380                    Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
381                                        NFCSTATUS_INVALID_DEVICE_REQUEST);
382                    break;
383                }
384            }
385            break;
386        }
387
388#ifdef PH_NDEF_MIFARE_ULC
389
390        case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES:
391        {
392            if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
393            {
394                Status = phFriNfc_MfUL_ParseTLVs (NdefSmtCrdFmt,
395                                        NdefSmtCrdFmt->SendRecvBuf,
396                                        (uint8_t)*NdefSmtCrdFmt->SendRecvLength);
397
398                if (!Status)
399                {
400                    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
401                        NdefSmtCrdFmt->AddInfo.Type2Info.LockBlockNumber;
402                    Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt);
403                }
404            }
405            else
406            {
407                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
408                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
409            }
410            break;
411        }
412
413        case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES:
414        {
415            if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength)
416            {
417                (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.ReadData,
418                            (void *)NdefSmtCrdFmt->SendRecvBuf,
419                            sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.ReadData));
420
421                NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0;
422
423                Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt);
424
425            }
426            else
427            {
428                Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
429                                    NFCSTATUS_INVALID_RECEIVE_LENGTH);
430            }
431            break;
432        }
433
434        case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES:
435        {
436            NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = (uint8_t)
437                                    (NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex +
438                                    MFUL_BLOCK_SIZE_IN_BYTES);
439
440            if (!phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt))
441            {
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);
445            }
446            else if ((NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex <
447                MIFARE_UL_READ_MAX_SIZE)
448                && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)))
449            {
450                /* If remaining lock bits has to be written and the data is already read */
451                Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt);
452            }
453            else
454            {
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);
460            }
461            break;
462        }
463
464#endif /* #ifdef PH_NDEF_MIFARE_ULC */
465
466        case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES:
467        {
468            /* Do nothing */
469            break;
470        }
471
472#endif /* #ifdef FRINFC_READONLY_NDEF */
473
474#ifdef PH_NDEF_MIFARE_ULC
475        case PH_FRINFC_MFUL_FMT_WR_TLV1:
476
477        break;
478#endif /* #ifdef PH_NDEF_MIFARE_ULC */
479
480        default:
481            Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
482                                NFCSTATUS_INVALID_DEVICE_REQUEST);
483            break;
484        }
485    }
486    /* Status is not success then call completion routine */
487    if(Status != NFCSTATUS_PENDING)
488    {
489        phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status);
490    }
491}
492
493#ifdef FRINFC_READONLY_NDEF
494
495#ifdef PH_NDEF_MIFARE_ULC
496
497static
498uint8_t
499phFriNfc_MfUL_GetSkipSize (
500    phFriNfc_sNdefSmtCrdFmt_t       *NdefSmtCrdFmt,
501    uint8_t                         block_number,
502    uint8_t                         byte_number)
503{
504    uint8_t                     skip_size = 0;
505    phFriNfc_Type2_AddInfo_t    *ps_type2_info =
506                                &NdefSmtCrdFmt->AddInfo.Type2Info;
507
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)
512    {
513        /* Only check for the lock control TLV */
514        if ((block_number == ps_type2_info->LockBlockNumber)
515            && (byte_number == ps_type2_info->LockByteNumber))
516        {
517            skip_size = MFUL_CONVERT_BITS_TO_BYTES(ps_type2_info->NoOfLockBits);
518        }
519    }
520
521    return skip_size;
522}
523
524static
525NFCSTATUS
526phFriNfc_MfUL_GetLockBytesInfo (
527    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt)
528{
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;
535
536
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);
539
540    lock_index = (lock_index + 1);
541    ps_type2_info->NoOfLockBits = ps_type2_info->DynLockBytes[lock_index];
542
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);
548
549    /* Apply the formula to calculate byte address
550        ByteAddr = ((PageAddr * (2 ^ BytesPerPage)) + ByteOffset)
551    */
552    ps_type2_info->LockByteNumber = (uint8_t)((page_address
553                                * (1 << ps_type2_info->LockBytesPerPage))
554                                + bytes_offset);
555
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);
560
561#if 0
562    if (
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)) ||
567
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))
575        )
576    {
577        ps_locktlv_info->ByteAddr = 0;
578        result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
579                            NFCSTATUS_NO_NDEF_SUPPORT);
580    }
581    else
582    {
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);
587    }
588#endif /* #if 0 */
589
590    return result;
591}
592
593static
594uint8_t
595phFriNfc_MfUL_CalcRemainingLockBits (
596    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt)
597{
598    uint8_t                         lock_bits_remaining = 0;
599    phFriNfc_Type2_AddInfo_t        *ps_type2_info =
600                                    &(NdefSmtCrdFmt->AddInfo.Type2Info);
601
602    lock_bits_remaining = (uint8_t)(ps_type2_info->NoOfLockBits -
603                                    ps_type2_info->LockBitsWritten);
604
605    return lock_bits_remaining;
606}
607
608static
609NFCSTATUS
610phFriNfc_MfUL_UpdateAndWriteLockBits (
611    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt)
612{
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;
625
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);
630
631    if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber)
632    {
633        /* 1st write to lock bits, so byte_index is updated */
634        byte_index = ps_type2_info->LockByteNumber;
635    }
636
637    no_of_bits_left_in_block = (uint8_t)((MFUL_BLOCK_SIZE_IN_BYTES - byte_index) *
638                                MFUL_BYTE_SIZE_IN_BITS);
639
640    if (no_of_bits_left_in_block >= remaining_lock_bits)
641    {
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)
647        {
648            /* mod operation has resulted in a value, means lock bits ends in between a byte */
649            uint8_t         mod_value = 0;
650
651            remaining_lock_bytes = ((remaining_lock_bits /
652                                    MFUL_BYTE_SIZE_IN_BITS) + 1);
653
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)
658            {
659                /* lock bits to write is greater than 8 bits */
660                while (lock_byte_index < (remaining_lock_bytes - 1))
661                {
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);
666                }
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,
673                                    mod_value, 1);
674            }
675            else
676            {
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,
682                                                        mod_value, 1);
683            }
684        } /* if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */
685        else
686        {
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);
691
692            while (lock_byte_index < remaining_lock_bytes)
693            {
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);
698            }
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) */
703    else
704    {
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))
708        {
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);
713        }
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) */
717
718
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));
723
724
725    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES;
726    result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
727
728    return result;
729}
730
731static
732NFCSTATUS
733phFriNfc_MfUL_ReadWriteLockBytes (
734    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt)
735{
736    NFCSTATUS                       result = NFCSTATUS_SUCCESS;
737    phFriNfc_Type2_AddInfo_t        *ps_type2_info =
738                                    &(NdefSmtCrdFmt->AddInfo.Type2Info);
739    uint8_t                         write_flag = FALSE;
740
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)))
748    {
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));
752        write_flag = TRUE;
753    }
754    else if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber)
755    {
756        /* Read is mandatory, First read and then update the block,
757            because chances are there that lock byte may start in between
758            the block */
759    }
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)))
763    {
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));
767        write_flag = TRUE;
768    }
769    else
770    {
771        /* Read is mandatory, First read and then update the block */
772    }
773
774    if (write_flag)
775    {
776        NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES;
777        result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
778    }
779    else
780    {
781        NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES;
782        result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
783    }
784
785    return result;
786}
787
788static
789NFCSTATUS
790phFriNfc_MfUL_GetDefaultLockBytesInfo (
791    phFriNfc_sNdefSmtCrdFmt_t          *NdefSmtCrdFmt)
792{
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;
797
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));
802
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);
807    /* Default settings
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);
811
812    return result;
813}
814
815static
816NFCSTATUS
817phFriNfc_MfUL_ParseTLVs (
818    phFriNfc_sNdefSmtCrdFmt_t       *NdefSmtCrdFmt,
819    uint8_t                         *data_to_parse,
820    uint8_t                         size_to_parse)
821{
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;
829
830    if ((0 == card_size_remaining) && (0 == parse_index))
831    {
832        /* card size is calculated only once */
833        card_size_remaining = (uint16_t)
834            (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8);
835    }
836
837    while ((parse_index < size_to_parse)
838        && (NFCSTATUS_SUCCESS == result)
839        && (NDEF_TLV_V != parse_tlv)
840        && (0 != card_size_remaining))
841    {
842        if (0 == skip_lock_mem_size)
843        {
844            /* Skip the lock TLVs, so get the lock bits */
845            skip_lock_mem_size = phFriNfc_MfUL_GetSkipSize (NdefSmtCrdFmt,
846                                        NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock,
847                                        parse_index);
848        }
849
850        if (0 != skip_lock_mem_size)
851        {
852            if (skip_lock_mem_size >= (size_to_parse - parse_index))
853            {
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;
860            }
861            else
862            {
863                card_size_remaining = (uint16_t)(card_size_remaining -
864                                        skip_lock_mem_size);
865
866                parse_index = (uint8_t)(parse_index + skip_lock_mem_size);
867                skip_lock_mem_size = 0;
868            }
869        }
870        else
871        {
872            switch (parse_tlv)
873            {
874                case LOCK_TLV_T:
875                {
876                    switch (*(data_to_parse + parse_index))
877                    {
878                        case MFUL_NULL_TLV:
879                        {
880                            /* Do nothing, parse further */
881                            break;
882                        }
883
884                        case LOCK_CTRL_TYPE_IN_TLV:
885                        {
886                            parse_tlv = LOCK_TLV_L;
887                            break;
888                        }
889
890                        case NDEF_TYPE_IN_TLV:
891                        {
892                            parse_tlv = NDEF_TLV_L;
893                            /* Default lock bytes shall be taken */
894                            NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag =
895                                                                            TRUE;
896                            result = phFriNfc_MfUL_GetDefaultLockBytesInfo (NdefSmtCrdFmt);
897                            break;
898                        }
899
900                        default:
901                        {
902                            parse_tlv = LOCK_TLV_T;
903                            result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
904                                                NFCSTATUS_NO_NDEF_SUPPORT);
905                            break;
906                        }
907                    }
908                    break;
909                }
910
911                case LOCK_TLV_L:
912                {
913                    if (LOCK_CTRL_LEN_IN_TLV == *(data_to_parse + parse_index))
914                    {
915                        parse_tlv = LOCK_TLV_V;
916                    }
917                    else
918                    {
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);
923                    }
924                    break;
925                }
926
927                case LOCK_TLV_V:
928                {
929                    switch (lock_mem_ndef_index)
930                    {
931                        case 0:
932                        case 1:
933                        {
934                            NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag =
935                                                                                FALSE;
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);
939                            break;
940                        }
941
942                        case 2:
943                        {
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);
949                            break;
950                        }
951
952                        default:
953                        {
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);
958                            break;
959                        }
960                    }
961                    break;
962                } /* switch (lock_mem_ndef_index) in case LOCK_TLV_V */
963
964                case NDEF_TLV_T:
965                {
966                    switch (*(data_to_parse + parse_index))
967                    {
968                        case MFUL_NULL_TLV:
969                        {
970                            /* Do nothing, parse further */
971                            break;
972                        }
973
974                        case NDEF_TYPE_IN_TLV:
975                        {
976                            parse_tlv = NDEF_TLV_L;
977                            break;
978                        }
979
980                        default:
981                        {
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);
986                            break;
987                        }
988                    }
989                    break;
990                } /* switch (*(data_to_parse + parse_index)) in case NDEF_TLV_T */
991
992                case NDEF_TLV_L:
993                {
994                    switch (lock_mem_ndef_index)
995                    {
996                        case 0:
997                        {
998                            if (THREE_BYTE_LENGTH_FIELD == *(data_to_parse + parse_index))
999                            {
1000                                lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
1001                            }
1002                            else
1003                            {
1004                                ndef_data_size = *(data_to_parse + parse_index);
1005                                parse_tlv = NDEF_TLV_V;
1006                                lock_mem_ndef_index = 0;
1007                            }
1008                            break;
1009                        }
1010
1011                        case 1:
1012                        {
1013                            ndef_data_size = (uint16_t)(*(data_to_parse + parse_index) << 8);
1014                            break;
1015                        }
1016
1017                        case 2:
1018                        {
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;
1023                            break;
1024                        }
1025                    } /* switch (lock_mem_ndef_index) in case NDEF_TLV_L */
1026                    break;
1027                }
1028
1029                case NDEF_TLV_V:
1030                {
1031                    break;
1032                }
1033
1034                default:
1035                {
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);
1040                    break;
1041                }
1042            } /* switch (parse_tlv) */
1043
1044        } /* else part of if (0 != skip_lock_mem_size) */
1045
1046        if (0 == card_size_remaining)
1047        {
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);
1052        }
1053        else if (NDEF_TLV_V != parse_tlv)
1054        {
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);
1059        }
1060        else
1061        {
1062            /* L field of the NDEF TLV
1063                L field can have 1 byte or also 3 bytes
1064               */
1065            uint8_t length_to_deduct = 1;
1066
1067            if ((NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION]
1068                * 8) >= THREE_BYTE_LENGTH_FIELD)
1069            {
1070                length_to_deduct = 3;
1071            }
1072            /* parse_tlv has reached the VALUE field of the NDEF TLV */
1073            if ((card_size_remaining - length_to_deduct) < ndef_data_size)
1074            {
1075                result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,
1076                                    NFCSTATUS_NO_NDEF_SUPPORT);
1077            }
1078
1079            lock_mem_ndef_index = 0;
1080            skip_lock_mem_size = 0;
1081            card_size_remaining = 0;
1082        }
1083    } /* while ((parse_index < size_to_parse)
1084        && (NFCSTATUS_SUCCESS != result)
1085        && (NDEF_TLV_V != parse_tlv)
1086        && (0 != card_size_remaining)) */
1087
1088    if ((NDEF_TLV_V == parse_tlv) || (NFCSTATUS_SUCCESS != result))
1089    {
1090        parse_tlv = LOCK_TLV_T;
1091    }
1092    else
1093    {
1094        NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES;
1095        NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
1096                        (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4);
1097
1098        result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt);
1099    }
1100
1101    if (NFCSTATUS_PENDING != result)
1102    {
1103        lock_mem_ndef_index = 0;
1104        skip_lock_mem_size = 0;
1105        card_size_remaining = 0;
1106    }
1107    return result;
1108}
1109
1110#endif /* #ifdef PH_NDEF_MIFARE_ULC */
1111
1112#endif /* #ifdef FRINFC_READONLY_NDEF */
1113
1114static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
1115{
1116    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1117
1118    /* Fill the send buffer */
1119    phFriNfc_MfUL_H_fillSendBuf(NdefSmtCrdFmt,
1120                            NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock);
1121
1122    /* Call transceive */
1123    Result = phFriNfc_MfUL_H_Transceive (NdefSmtCrdFmt);
1124
1125    return Result;
1126}
1127
1128static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t    *NdefSmtCrdFmt)
1129{
1130    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1131
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;
1136
1137    /*set the completion routines for the card operations*/
1138    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process;
1139    NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt;
1140
1141    *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE;
1142
1143    /* Call the Overlapped HAL Transceive function */
1144    Result = phFriNfc_OvrHal_Transceive(    NdefSmtCrdFmt->LowerDevice,
1145                                            &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo,
1146                                            NdefSmtCrdFmt->psRemoteDevInfo,
1147                                            NdefSmtCrdFmt->Cmd,
1148                                            &NdefSmtCrdFmt->psDepAdditionalInfo,
1149                                            NdefSmtCrdFmt->SendRecvBuf,
1150                                            NdefSmtCrdFmt->SendLength,
1151                                            NdefSmtCrdFmt->SendRecvBuf,
1152                                            NdefSmtCrdFmt->SendRecvLength);
1153    return Result;
1154}
1155
1156static void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,
1157                                 uint8_t                    BlockNo)
1158{
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};
1164
1165
1166
1167
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)
1171    {
1172#ifdef FRINFC_READONLY_NDEF
1173
1174        case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES:
1175        {
1176#ifdef PH_HAL4_ENABLE
1177            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1178#else
1179        /* Read command */
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;
1185            break;
1186        }
1187
1188#ifdef PH_NDEF_MIFARE_ULC
1189
1190        case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES:
1191        {
1192#ifdef PH_HAL4_ENABLE
1193            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1194#else
1195        /* Read command */
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;
1202            break;
1203        }
1204
1205        case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES:
1206        {
1207#ifdef PH_HAL4_ENABLE
1208            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1209#else
1210        /* Read command */
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;
1216            break;
1217        }
1218
1219        case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES:
1220        {
1221#ifdef PH_HAL4_ENABLE
1222            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1223#else
1224            /* Write command */
1225            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1226#endif /* #ifdef PH_HAL4_ENABLE */
1227
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);
1234            break;
1235        }
1236
1237#endif /* #ifdef PH_NDEF_MIFARE_ULC */
1238
1239        case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES:
1240        {
1241#ifdef PH_HAL4_ENABLE
1242            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1243#else
1244            /* Read command */
1245            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1246#endif /* #ifdef PH_HAL4_ENABLE */
1247
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);
1254            break;
1255        }
1256
1257        case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES:
1258        {
1259#ifdef PH_HAL4_ENABLE
1260            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1261#else
1262            /* Read command */
1263            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1264#endif /* #ifdef PH_HAL4_ENABLE */
1265
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);
1272            break;
1273        }
1274
1275#endif /* #ifdef FRINFC_READONLY_NDEF */
1276
1277    case PH_FRINFC_MFUL_FMT_RD_16BYTES:
1278#ifdef PH_HAL4_ENABLE
1279        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead;
1280#else
1281        /* Read command */
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;
1286        break;
1287
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;
1291        /* Write command */
1292#ifdef PH_HAL4_ENABLE
1293        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1294#else
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);
1301        break;
1302
1303    case PH_FRINFC_MFUL_FMT_WR_TLV:
1304#ifndef PH_NDEF_MIFARE_ULC
1305    default:
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;
1309        /* Write command */
1310#ifdef PH_HAL4_ENABLE
1311        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1312#else
1313        NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4;
1314#endif /* #ifdef PH_HAL4_ENABLE */
1315        /* Copy the NDEF TLV */
1316#ifdef PH_NDEF_MIFARE_ULC
1317
1318        if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
1319        {
1320            (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1321                    NDEFTLV1,
1322                    PH_FRINFC_MFUL_FMT_VAL_4);
1323        }
1324        else if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD)
1325        {
1326            (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1327                NDEFTLV,
1328                PH_FRINFC_MFUL_FMT_VAL_4);
1329        }
1330        else
1331        {
1332        }
1333#else
1334        (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1335                    NDEFTLV,
1336                    PH_FRINFC_MFUL_FMT_VAL_4);
1337
1338#endif /* #ifdef PH_NDEF_MIFARE_ULC */
1339
1340        break;
1341
1342#ifdef PH_NDEF_MIFARE_ULC
1343    case PH_FRINFC_MFUL_FMT_WR_TLV1:
1344        if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD)
1345        {
1346            /* Send length for write command is always Five */
1347            NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5;
1348            /* Write command */
1349            NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4;
1350            (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1],
1351                        NDEFTLV2,
1352                        PH_FRINFC_MFUL_FMT_VAL_4);
1353        }
1354        break;
1355    default:
1356        break;
1357#endif /* #ifdef PH_NDEF_MIFARE_ULC */
1358
1359
1360    }
1361}
1362
1363static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
1364{
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};
1369
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 */
1374
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))
1380    {
1381
1382#ifdef PH_NDEF_MIFARE_ULC
1383
1384        if (NdefSmtCrdFmt->SendRecvBuf[8] == 0x02 &&
1385            NdefSmtCrdFmt->SendRecvBuf[9] == 0x00)
1386        {
1387            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD;
1388
1389            (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1390                        OTPByteULC,
1391                        sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
1392        }
1393        else if (NdefSmtCrdFmt->SendRecvBuf[8] == 0xFF &&
1394                NdefSmtCrdFmt->SendRecvBuf[9] == 0xFF)
1395        {
1396            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
1397
1398            (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes,
1399                        OTPByteUL,
1400                        sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes));
1401        }
1402        else
1403        {
1404            NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD;
1405        }
1406
1407#endif /* #ifdef PH_NDEF_MIFARE_ULC */
1408
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);
1413
1414        if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0)
1415        {
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;
1421        }
1422        else
1423        {
1424            /* IS the card new, OTP bytes = {0x00, 0x00, 0x00, 0x00} */
1425            memcompare = (uint32_t)MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4],
1426                                ZeroBuf,
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)
1430            {
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;
1436            }
1437        }
1438    }
1439
1440
1441
1442#ifdef PH_NDEF_MIFARE_ULC
1443    if(
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))
1448        )
1449#else
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 */
1453    {
1454        Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
1455    }
1456    return Result;
1457}
1458
1459static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt )
1460{
1461    NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1462    /* Card already have the OTP bytes so write TLV */
1463    NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV;
1464
1465    /* Write NDEF TLV in block number 4 */
1466    NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock =
1467                                PH_FRINFC_MFUL_FMT_VAL_4;
1468
1469    Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt);
1470    return Result;
1471}
1472
1473