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_TopazMap.c
19 * \brief NFC Ndef Mapping For Remote Devices.
20 *
21 * Project: NFC-FRI
22 *
23 * $Date: Mon Dec 13 14:14:14 2010 $
24 * $Author: ing02260 $
25 * $Revision: 1.23 $
26 * $Aliases:  $
27 *
28 */
29 
30 
31 
32 #include <phFriNfc_NdefMap.h>
33 #include <phFriNfc_TopazMap.h>
34 #include <phFriNfc_MapTools.h>
35 #include <phFriNfc_OvrHal.h>
36 
37 #ifndef PH_FRINFC_MAP_TOPAZ_DISABLED
38 /*! \ingroup grp_file_attributes
39 *  \name NDEF Mapping
40 *
41 * File: \ref phFriNfcNdefMap.c
42 *
43 */
44 /*@{*/
45 #define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.23 $"
46 #define PHFRINFCTOPAZMAP_FILEALIASES  "$Aliases:  $"
47 /*@}*/
48 /****************** Start of macros ********************/
49 /* Below MACRO is used for the WRITE error scenario,
50     in case PN544 returns error for any WRITE, then
51     read the written block and byte number, to check the data
52     written to the card is correct or not
53 */
54 /* #define TOPAZ_RF_ERROR_WORKAROUND */
55 
56 #ifdef FRINFC_READONLY_NDEF
57 
58     #define CC_BLOCK_NUMBER                                         (0x01U)
59     #define LOCK_BLOCK_NUMBER                                       (0x0EU)
60 
61     #define LOCK0_BYTE_NUMBER                                       (0x00U)
62     #define LOCK0_BYTE_VALUE                                        (0xFFU)
63 
64     #define LOCK1_BYTE_NUMBER                                       (0x01U)
65     #define LOCK1_BYTE_VALUE                                        (0x7FU)
66 
67     #define CC_RWA_BYTE_NUMBER                                      (0x03U)
68     #define CC_READ_ONLY_VALUE                                      (0x0FU)
69 
70 #endif /* #ifdef FRINFC_READONLY_NDEF */
71 
72 #ifdef TOPAZ_RF_ERROR_WORKAROUND
73 
74     /* Below MACROs are added for the error returned from HAL, if the
75         below error has occured during the WRITE, then read the error
76         returned blocks to confirm */
77     #define FRINFC_RF_TIMEOUT_89                                    (0x89U)
78     #define FRINFC_RF_TIMEOUT_90                                    (0x90U)
79 
80     /* State specific to read after the RF ERROR for the WRITE */
81     #define PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ                     (0x0FU)
82 
83 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
84 
85 /****************** End of macros ********************/
86 
87 /*!
88 * \name Topaz Mapping - Helper Functions
89 *
90 */
91 /*@{*/
92 
93 /*!
94 * \brief \copydoc page_ovr Helper function for Topaz. This function shall read 8 bytes
95 *  from the card.
96 */
97 static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap,
98                                         uint16_t             BlockNo,
99                                         uint16_t             ByteNo);
100 
101 /*!
102 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process
103 * read id command
104 */
105 static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap);
106 
107 /*!
108 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process
109 * read all command
110 */
111 static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap);
112 
113 /*!
114 * \brief \copydoc page_ovr Helper function for Topaz. This function depends on
115 * function called by the user
116 */
117 static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap);
118 
119 /*!
120 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC
121 * bytes
122 */
123 static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap);
124 
125 /*!
126 * \brief \copydoc page_ovr Helper function for Topaz. This function finds
127 * NDEF TLV
128 */
129 static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap);
130 
131 /*!
132 * \brief \copydoc page_ovr Helper function for Topaz. This function writes a
133 * byte into the card
134 */
135 static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap,
136                                         uint16_t             BlockNo,
137                                         uint16_t             ByteNo,
138                                         uint8_t              ByteVal
139                                         );
140 
141 /*!
142 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process the
143 * NMN write
144 */
145 static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap);
146 
147 /*!
148 * \brief \copydoc page_ovr Helper function for Topaz. This function writes the length field of
149 * the NDEF TLV
150 */
151 static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap);
152 
153 /*!
154 * \brief \copydoc page_ovr Helper function for Topaz. This function updates length field
155 * of the NDEF TLV after complete write.
156 */
157 static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t  *NdefMap);
158 
159 /*!
160 * \brief \copydoc page_ovr Helper function for Topaz. This function copies the card data
161 *  to the user buffer
162 */
163 static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf( phFriNfc_NdefMap_t  *NdefMap);
164 
165 /*!
166 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process the
167 * written data
168 */
169 static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData( phFriNfc_NdefMap_t  *NdefMap);
170 
171 /*!
172 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the block
173 * number is correct or not
174 */
175 static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t  *NdefMap);
176 
177 /*!
178 * \brief \copydoc page_ovr Helper function for Topaz. This function writes the 0th
179 * byte of block 1 has Zero
180 */
181 static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t   *NdefMap);
182 
183 /*!
184 * \brief \copydoc page_ovr Helper function for Topaz. This function calls the
185 * completion routine
186 */
187 static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t  *NdefMap,
188                                     NFCSTATUS           Status);
189 
190 /*!
191 * \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks
192 * the CC byte in check ndef function
193 */
194 static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t  *NdefMap);
195 
196 /*!
197 * \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks
198 * the lock bits and set a card state
199 */
200 static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t  *NdefMap);
201 
202 /*!
203 * \brief \copydoc page_ovr Helper function for Topaz. This function writes CC bytes or
204 * type of the TLV
205 */
206 static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t  *NdefMap);
207 
208 #ifdef TOPAZ_RF_ERROR_WORKAROUND
209 
210 /*!
211 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the written
212 * value after the
213 */
214 static
215 NFCSTATUS
216 phFriNfc_Tpz_H_CheckWrittenData (
217     phFriNfc_NdefMap_t          *psNdefMap,
218     uint8_t                     state_rf_error);
219 
220 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
221 
222 /*!
223 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the written
224 * CC bytes are correct
225 */
226 static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t  *NdefMap);
227 /*@}*/
phFriNfc_TopazMap_H_Reset(phFriNfc_NdefMap_t * NdefMap)228 void phFriNfc_TopazMap_H_Reset(phFriNfc_NdefMap_t        *NdefMap)
229 {
230     /* Initialising the Topaz structure variable */
231     NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_INVALID_OPE;
232     NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
233     NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
234     NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_VAL0;
235     (void)memset(NdefMap->TopazContainer.ReadBuffer, PH_FRINFC_TOPAZ_VAL0,
236                 sizeof(NdefMap->TopazContainer.ReadBuffer));
237     NdefMap->TopazContainer.ReadWriteCompleteFlag = PH_FRINFC_TOPAZ_FLAG0;
238     NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_VAL0;
239     (void)memset(NdefMap->TopazContainer.UID, PH_FRINFC_TOPAZ_VAL0,
240                 sizeof(NdefMap->TopazContainer.UID));
241     NdefMap->TopazContainer.Cur_RW_Index=0;
242     NdefMap->TopazContainer.ByteRWFrmCard =0;
243 }
244 
245 /*!
246 * \brief Check whether a particular Remote Device is NDEF compliant.
247 *
248 * The function checks whether the peer device is NDEF compliant.
249 *
250 * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t
251 *                    structure describing the component context.
252 *
253 * \retval  NFCSTATUS_PENDING   The action has been successfully triggered.
254 * \retval  Others              An error has occurred.
255 *
256 */
257 
phFriNfc_TopazMap_ChkNdef(phFriNfc_NdefMap_t * NdefMap)258 NFCSTATUS phFriNfc_TopazMap_ChkNdef( phFriNfc_NdefMap_t     *NdefMap)
259 {
260     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
261         NFCSTATUS_INVALID_PARAMETER);
262     if ( NdefMap != NULL)
263     {
264         /* Update the previous operation */
265         NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE;
266         /* Update the CR index to know from which operation completion
267         routine has to be called */
268         NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF;
269         NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
270         NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
271 
272         /* Set card state */
273         NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_CARD;
274 
275         /* Change the state to Check Ndef Compliant */
276         NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID;
277         NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE;
278 
279 #ifdef TOPAZ_RAW_SUPPORT
280         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
281         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID;
282 #else
283 #ifdef PH_HAL4_ENABLE
284         NdefMap->Cmd.JewelCmd = phHal_eJewel_RID;
285 #else
286         NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid;
287 #endif
288 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
289 
290         Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock,
291             NdefMap->TopazContainer.ByteNumber);
292     }
293     return Result;
294 }
295 
296 #ifdef FRINFC_READONLY_NDEF
297 
298 NFCSTATUS
phFriNfc_TopazMap_ConvertToReadOnly(phFriNfc_NdefMap_t * NdefMap)299 phFriNfc_TopazMap_ConvertToReadOnly (
300     phFriNfc_NdefMap_t          *NdefMap)
301 {
302     NFCSTATUS               result = NFCSTATUS_SUCCESS;
303 
304     result = phFriNfc_Tpz_H_WrAByte (NdefMap, CC_BLOCK_NUMBER,
305                                     CC_RWA_BYTE_NUMBER, CC_READ_ONLY_VALUE);
306 
307     if (NFCSTATUS_PENDING == PHNFCSTATUS(result))
308     {
309         NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_BYTE;
310     }
311     return result;
312 }
313 
314 #endif /* #ifdef FRINFC_READONLY_NDEF */
315 
316 /*!
317 * \brief Initiates Reading of NDEF information from the Remote Device.
318 *
319 * The function initiates the reading of NDEF information from a Remote Device.
320 * It performs a reset of the state and starts the action (state machine).
321 * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action
322 * has been triggered.
323 */
phFriNfc_TopazMap_RdNdef(phFriNfc_NdefMap_t * NdefMap,uint8_t * PacketData,uint32_t * PacketDataLength,uint8_t Offset)324 NFCSTATUS phFriNfc_TopazMap_RdNdef( phFriNfc_NdefMap_t                  *NdefMap,
325                                         uint8_t                         *PacketData,
326                                         uint32_t                        *PacketDataLength,
327                                         uint8_t                         Offset)
328 {
329     NFCSTATUS               Result =    NFCSTATUS_SUCCESS;
330 
331     /* Copy user buffer to the context */
332     NdefMap->ApduBuffer = PacketData;
333     /* Copy user length to the context */
334     NdefMap->ApduBufferSize = *PacketDataLength;
335     /* Update the user memory size to a context variable */
336     NdefMap->NumOfBytesRead = PacketDataLength;
337     /* Number of bytes read from the card is zero.
338     This variable returns the number of bytes read
339     from the card. */
340     *NdefMap->NumOfBytesRead = PH_FRINFC_TOPAZ_VAL0;
341     /* Index to know the length read */
342     NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0;
343     /* Store the offset in the context */
344     NdefMap->Offset = Offset;
345     /* Update the CR index to know from which operation completion
346     routine has to be called */
347     NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF;
348 
349     if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation ==
350         PH_FRINFC_NDEFMAP_WRITE_OPE))
351     {
352         /* If previous operation is not read then the read shall
353         start from BEGIN */
354         NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
355         /* Initialise current block and byte number */
356         NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
357         NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
358         /* State has to be changed */
359         NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL;
360         NdefMap->TopazContainer.ReadWriteCompleteFlag =
361             PH_FRINFC_TOPAZ_FLAG0;
362         /* Topaz command = READALL */
363 #ifdef TOPAZ_RAW_SUPPORT
364         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
365         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL;
366 #else
367 
368 #ifdef PH_HAL4_ENABLE
369         NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll;
370 #else
371         NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll;
372 #endif
373 
374 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
375     }
376 
377     NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE;
378     /* Offset = Current, but the read has reached the End of Card */
379     if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) &&
380         (NdefMap->TopazContainer.ReadWriteCompleteFlag ==
381         PH_FRINFC_TOPAZ_FLAG1))
382     {
383         Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
384             NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
385     }
386     else
387     {
388         /* if the offset is begin then call READALL else copy the data
389         from the user buffer */
390         Result = ((Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
391             phFriNfc_Tpz_H_RdBytes(NdefMap,
392             NdefMap->TopazContainer.CurrentBlock,
393             NdefMap->TopazContainer.ByteNumber):
394         phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap));
395     }
396 
397     return Result;
398 }
399 
400 /*!
401 * \brief Initiates Writing of NDEF information to the Remote Device.
402 *
403 * The function initiates the writing of NDEF information to a Remote Device.
404 * It performs a reset of the state and starts the action (state machine).
405 * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action
406 * has been triggered.
407 */
phFriNfc_TopazMap_WrNdef(phFriNfc_NdefMap_t * NdefMap,uint8_t * PacketData,uint32_t * PacketDataLength,uint8_t Offset)408 NFCSTATUS phFriNfc_TopazMap_WrNdef( phFriNfc_NdefMap_t     *NdefMap,
409                                    uint8_t                 *PacketData,
410                                    uint32_t                *PacketDataLength,
411                                    uint8_t                 Offset)
412 {
413     NFCSTATUS                   Result =    NFCSTATUS_SUCCESS;
414     uint8_t TempByteVal = 0;
415     /* Copy user buffer to the context */
416     NdefMap->ApduBuffer = PacketData;
417     /* Copy user length to the context */
418     NdefMap->ApduBufferSize = *PacketDataLength;
419     /* Index to know the length written */
420     NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0;
421     /* Update the user memory size to a context variable */
422     NdefMap->WrNdefPacketLength = PacketDataLength;
423     /* Number of bytes written to the card is zero.
424     This variable returns the number of bytes written
425     to the card. */
426     *NdefMap->WrNdefPacketLength = PH_FRINFC_TOPAZ_VAL0;
427     /* Update the CR index to know from which operation completion
428     routine has to be called */
429     NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF;
430     /* Store the offset in the context */
431     NdefMap->Offset = Offset;
432 
433 
434     if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) ||
435         (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))
436     {
437         NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
438         /* Initialise current block and byte number */
439         NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1;
440         NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0;
441         /* State has to be changed */
442         NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL;
443         /* Topaz command = READALL */
444 
445 #ifdef TOPAZ_RAW_SUPPORT
446         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
447         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL;
448 #else
449 #ifdef PH_HAL4_ENABLE
450         NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll;
451 #else
452         NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll;
453 #endif
454 #endif  /* #ifdef TOPAZ_RAW_SUPPORT */
455         NdefMap->TopazContainer.ReadWriteCompleteFlag =
456             PH_FRINFC_TOPAZ_FLAG0;
457         NdefMap->TopazContainer.RemainingSize = NdefMap->CardMemSize;
458         TempByteVal = NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1];
459     }
460     else
461     {
462         /* State has to be changed */
463         NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
464         /* copy the user data to write into the card */
465         TempByteVal = NdefMap->ApduBuffer[NdefMap->ApduBuffIndex];
466     }
467 
468     /* Update the previous operation to write operation */
469     NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE;
470     if((Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) &&
471         (NdefMap->TopazContainer.ReadWriteCompleteFlag ==
472         PH_FRINFC_TOPAZ_FLAG1))
473     {
474         /* Offset = Current, but the read has reached the End of Card */
475         Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
476             NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
477     }
478     else
479     {
480         /* Check the block */
481         phFriNfc_Tpz_H_BlkChk(NdefMap);
482         /* if offset is begin then call READALL else start writing */
483         Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
484             phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock,
485             NdefMap->TopazContainer.ByteNumber):
486             phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock,
487             NdefMap->TopazContainer.ByteNumber,TempByteVal));
488     }
489 
490     return Result;
491 }
492 
493 
494 /*!
495 * \brief Completion Routine, Processing function, needed to avoid long blocking.
496 * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion
497 *       Routine in order to be able to notify the component that an I/O has finished and data are
498 *       ready to be processed.
499 *
500 */
501 
phFriNfc_TopazMap_Process(void * Context,NFCSTATUS Status)502 void phFriNfc_TopazMap_Process( void       *Context,
503                                NFCSTATUS   Status)
504 {
505 
506     phFriNfc_NdefMap_t              *psNdefMap = NULL;
507 
508 #ifdef TOPAZ_RF_ERROR_WORKAROUND
509 
510     static uint8_t                  rf_error_state = 0;
511 
512 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
513 #ifdef FRINFC_READONLY_NDEF
514     static uint8_t                  written_lock_byte = 0;
515 #endif /* #ifdef FRINFC_READONLY_NDEF */
516 
517     psNdefMap = (phFriNfc_NdefMap_t *)Context;
518 
519     if ((Status & PHNFCSTBLOWER) == (NFCSTATUS_SUCCESS & PHNFCSTBLOWER))
520     {
521         switch (psNdefMap->State)
522         {
523 #ifdef FRINFC_READONLY_NDEF
524             case PH_FRINFC_TOPAZ_STATE_WR_CC_BYTE:
525             {
526                 if((CC_READ_ONLY_VALUE == *psNdefMap->SendRecvBuf)
527                     && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength))
528                 {
529                     written_lock_byte = 0;
530 #ifdef TOPAZ_RAW_SUPPORT
531                     *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ;
532 #else
533 #ifdef PH_HAL4_ENABLE
534                     psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1;
535 #else
536                     psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1;
537 #endif /* #ifdef PH_HAL4_ENABLE */
538 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
539                     Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, LOCK_BLOCK_NUMBER,
540                                                     LOCK0_BYTE_NUMBER);
541 
542                     if (NFCSTATUS_PENDING == PHNFCSTATUS(Status))
543                     {
544                         psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_LOCK0_BYTE;
545                     }
546                 }
547                 else
548                 {
549                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
550                                         NFCSTATUS_INVALID_RECEIVE_LENGTH);
551                 }
552                 break;
553             }
554 
555             case PH_FRINFC_TOPAZ_STATE_RD_LOCK0_BYTE:
556             {
557                 if (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength)
558                 {
559                     Status = phFriNfc_Tpz_H_WrAByte (psNdefMap, LOCK_BLOCK_NUMBER,
560                                                 LOCK0_BYTE_NUMBER,
561                                                 LOCK0_BYTE_VALUE);
562 
563                     if (NFCSTATUS_PENDING == PHNFCSTATUS(Status))
564                     {
565                         psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_LOCK0_BYTE;
566                     }
567                 }
568                 break;
569             }
570 
571             case PH_FRINFC_TOPAZ_STATE_WR_LOCK0_BYTE:
572             {
573                 if((LOCK0_BYTE_VALUE == *psNdefMap->SendRecvBuf)
574                     && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength))
575                 {
576 #ifdef TOPAZ_RAW_SUPPORT
577                     *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ;
578 #else
579 #ifdef PH_HAL4_ENABLE
580                     psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1;
581 #else
582                     psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1;
583 #endif /* #ifdef PH_HAL4_ENABLE */
584 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
585                     Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, LOCK_BLOCK_NUMBER,
586                                                     LOCK1_BYTE_NUMBER);
587 
588                     if (NFCSTATUS_PENDING == PHNFCSTATUS(Status))
589                     {
590                         psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_LOCK1_BYTE;
591                     }
592                 }
593                 else
594                 {
595                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
596                                         NFCSTATUS_INVALID_RECEIVE_LENGTH);
597                 }
598             }
599 
600             case PH_FRINFC_TOPAZ_STATE_RD_LOCK1_BYTE:
601             {
602                 if (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength)
603                 {
604                     written_lock_byte = (uint8_t)(*psNdefMap->SendRecvBuf | LOCK1_BYTE_VALUE);
605                     Status = phFriNfc_Tpz_H_WrAByte (psNdefMap, LOCK_BLOCK_NUMBER,
606                                                 LOCK1_BYTE_NUMBER,
607                                                 written_lock_byte);
608 
609                     if (NFCSTATUS_PENDING == PHNFCSTATUS(Status))
610                     {
611                         psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_LOCK1_BYTE;
612                     }
613                 }
614                 break;
615             }
616 
617             case PH_FRINFC_TOPAZ_STATE_WR_LOCK1_BYTE:
618             {
619                 if((written_lock_byte == *psNdefMap->SendRecvBuf)
620                     && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength))
621                 {
622                     written_lock_byte = 0;
623                     /* Do nothing */
624                 }
625                 else
626                 {
627                     written_lock_byte = 0;
628                     Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
629                                         NFCSTATUS_INVALID_RECEIVE_LENGTH);
630                 }
631             }
632 #endif /* #ifdef FRINFC_READONLY_NDEF */
633             case PH_FRINFC_TOPAZ_STATE_WRITE:
634             {
635                 Status = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap);
636                 break;
637             }
638 
639             case PH_FRINFC_TOPAZ_STATE_READID:
640             {
641                 Status = phFriNfc_Tpz_H_ProReadID (psNdefMap);
642                 break;
643             }
644 
645             case PH_FRINFC_TOPAZ_STATE_READALL:
646             {
647                 Status = phFriNfc_Tpz_H_ProReadAll (psNdefMap);
648                 break;
649             }
650 
651             case PH_FRINFC_TOPAZ_STATE_WRITE_NMN:
652             {
653                 Status = phFriNfc_Tpz_H_ProWrNMN (psNdefMap);
654                 break;
655             }
656 
657             case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV:
658             {
659                 Status = phFriNfc_Tpz_H_ProWrTLV (psNdefMap);
660                 break;
661             }
662 
663             case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV:
664             {
665                 Status = phFriNfc_Tpz_H_ProCCTLV (psNdefMap);
666                 break;
667             }
668 
669 #ifdef TOPAZ_RF_ERROR_WORKAROUND
670 
671             case PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ:
672             {
673                 Status = phFriNfc_Tpz_H_CheckWrittenData (psNdefMap,
674                                                         rf_error_state);
675                 break;
676             }
677 
678 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
679 
680             default:
681             {
682                 Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_MAP,
683                                     NFCSTATUS_INVALID_DEVICE_REQUEST);
684                 break;
685             }
686         }
687     }
688     else
689     {
690 #ifdef TOPAZ_RF_ERROR_WORKAROUND
691 
692         if ((FRINFC_RF_TIMEOUT_89 == PHNFCSTATUS (Status)) ||
693             (FRINFC_RF_TIMEOUT_90 == PHNFCSTATUS (Status)) ||
694             (NFCSTATUS_RF_TIMEOUT == PHNFCSTATUS (Status)))
695         {
696             uint8_t             byte_number = 0;
697             uint8_t             block_number = 0;
698 
699             rf_error_state = psNdefMap->State;
700 
701 #ifdef TOPAZ_RAW_SUPPORT
702 
703             *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ;
704 
705 #else
706 
707 #ifdef PH_HAL4_ENABLE
708 
709             psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1;
710 
711 #else
712 
713             psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1;
714 
715 #endif /* #ifdef PH_HAL4_ENABLE */
716 
717 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
718 
719             /* Update the state variable to the new work around state*/
720             psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ;
721 
722             /* Switch is used to know, if the error occured during WRITE or READ */
723             switch (rf_error_state)
724             {
725                 case PH_FRINFC_TOPAZ_STATE_WRITE_NMN:
726                 {
727                     /* Block and byte number is updated for NMN */
728                     byte_number = PH_FRINFC_TOPAZ_VAL0;
729                     block_number = PH_FRINFC_TOPAZ_VAL1;
730                     break;
731                 }
732 
733                 case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV:
734                 {
735                     /* Get the L field of the TLV block */
736                     block_number = (uint8_t)(((psNdefMap->TLVStruct.NdefTLVByte +
737                                         PH_FRINFC_TOPAZ_VAL1) >
738                                         PH_FRINFC_TOPAZ_VAL7)?
739                                         (psNdefMap->TLVStruct.NdefTLVBlock +
740                                         PH_FRINFC_TOPAZ_VAL1):
741                                         psNdefMap->TLVStruct.NdefTLVBlock);
742                     /* Get the L byte */
743                     byte_number = (uint8_t)((psNdefMap->TLVStruct.NdefTLVByte +
744                                         PH_FRINFC_TOPAZ_VAL1) %
745                                         PH_FRINFC_TOPAZ_VAL8);
746                     break;
747                 }
748 
749                 case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV:
750                 {
751                     switch (psNdefMap->TopazContainer.InternalState)
752                     {
753                         case PH_FRINFC_TOPAZ_WR_CC_BYTE0:
754                         {
755                             /* Block and byte number is updated for the CC byte 0 */
756                             block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
757                             byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL0;
758                             break;
759                         }
760 
761                         case PH_FRINFC_TOPAZ_WR_CC_BYTE1:
762                         {
763                             /* Block and byte number is updated for the CC byte 1 */
764                             block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
765                             byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
766                             break;
767                         }
768 
769                         case PH_FRINFC_TOPAZ_WR_CC_BYTE2:
770                         {
771                             /* Block and byte number is updated for the CC byte 2 */
772                             block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
773                             byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL2;
774                             break;
775                         }
776 
777                         case PH_FRINFC_TOPAZ_WR_CC_BYTE3:
778                         {
779                             /* Block and byte number is updated for the CC byte 3 */
780                             block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
781                             byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL3;
782                             break;
783                         }
784 
785                         case PH_FRINFC_TOPAZ_WR_T_OF_TLV:
786                         {
787                             /* Block and byte number is updated for the Type field of the TLV */
788                             block_number = psNdefMap->TLVStruct.NdefTLVBlock;
789                             byte_number = (uint8_t)psNdefMap->TLVStruct.NdefTLVByte;
790                             break;
791                         }
792 
793                         default:
794                         {
795                             /* Do nothing */
796                             break;
797                         }
798                     } /* switch (psNdefMap->TopazContainer.InternalState) */
799                     break;
800                 }
801 
802                 case PH_FRINFC_TOPAZ_STATE_WRITE:
803                 {
804                     /* Block and byte number is updated for the written error data */
805                     block_number = psNdefMap->TopazContainer.CurrentBlock;
806                     byte_number = psNdefMap->TopazContainer.ByteNumber;
807                     break;
808                 }
809 
810                 default:
811                 {
812                     /* Error occured is not during WRITE, so update
813                         state variable to the previous state */
814                     psNdefMap->State = rf_error_state;
815                     break;
816                 }
817             } /* switch (rf_error_state) */
818 
819             /* The below check is added, to know if the error is for
820             the WRITE or READ scenario,
821             If the error is for READ, then state variable is not updated
822             If the error is for WRITE, then state variable is updated with
823             PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ value */
824             if (PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ == psNdefMap->State)
825             {
826                 /* Read the data with the updated block and byte number */
827                 Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, block_number,
828                                                 byte_number);
829             }
830         }
831 
832 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
833     }
834 
835     /* Call Completion Routine, if Status != PENDING */
836     if (NFCSTATUS_PENDING != Status)
837     {
838         phFriNfc_Tpz_H_Complete(psNdefMap, Status);
839     }
840 }
841 
842 
843 #ifdef TOPAZ_RF_ERROR_WORKAROUND
844 
845 static
846 NFCSTATUS
phFriNfc_Tpz_H_CheckWrittenData(phFriNfc_NdefMap_t * psNdefMap,uint8_t state_rf_error)847 phFriNfc_Tpz_H_CheckWrittenData (
848     phFriNfc_NdefMap_t          *psNdefMap,
849     uint8_t                     state_rf_error)
850 {
851     NFCSTATUS   result = NFCSTATUS_SUCCESS;
852 
853     switch (state_rf_error)
854     {
855         case PH_FRINFC_TOPAZ_STATE_WRITE:
856         {
857             result = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap);
858             break;
859         }
860 
861         case PH_FRINFC_TOPAZ_STATE_WRITE_NMN:
862         {
863             result = phFriNfc_Tpz_H_ProWrNMN (psNdefMap);
864             break;
865         }
866 
867         case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV:
868         {
869             result = phFriNfc_Tpz_H_ProWrTLV (psNdefMap);
870             break;
871         }
872 
873         case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV:
874         {
875             result = phFriNfc_Tpz_H_ProCCTLV (psNdefMap);
876             break;
877         }
878 
879         default:
880         {
881             break;
882         }
883     }
884 
885     return result;
886 }
887 
888 
889 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */
890 
phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t * NdefMap,uint16_t BlockNo,uint16_t ByteNo)891 static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap,
892                                         uint16_t             BlockNo,
893                                         uint16_t            ByteNo)
894 {
895     NFCSTATUS   Result = NFCSTATUS_SUCCESS;
896 #ifdef TOPAZ_RAW_SUPPORT
897     uint8_t index = 0;
898 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
899 
900     /* set the data for additional data exchange*/
901     NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
902     NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
903     NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
904 
905     NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process;
906     NdefMap->MapCompletionInfo.Context = NdefMap;
907 
908     *NdefMap->SendRecvLength = NdefMap->TempReceiveLength;
909 
910     /* Depending on the jewel command, the send length is decided */
911 #ifdef TOPAZ_RAW_SUPPORT
912     switch(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0])
913 #else
914     switch(NdefMap->Cmd.JewelCmd)
915 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
916     {
917 
918 #ifdef TOPAZ_RAW_SUPPORT
919     case PH_FRINFC_TOPAZ_CMD_READID:
920 #else
921 #ifdef PH_HAL4_ENABLE
922     case phHal_eJewel_RID:
923 #else
924     case phHal_eJewelCmdListJewelRid:
925 #endif
926 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
927 
928 #ifdef TOPAZ_RAW_SUPPORT
929         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
930         /*Copy command to  Send Buffer*/
931         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_READID;
932         index ++;
933 
934         /*Copy UID of the tag to  Send Buffer*/
935         (void)memset(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]),
936         0x00,(0x06));
937         index = index + 0x06;
938 
939         /* Update the length of the command buffer*/
940         NdefMap->SendLength = index;
941 #else
942         /* For READ ID and READ ALL, send length is 0 */
943         NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0;
944 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
945         break;
946 
947 #ifdef TOPAZ_RAW_SUPPORT
948     case PH_FRINFC_TOPAZ_CMD_READALL:
949 #else
950 #ifdef PH_HAL4_ENABLE
951     case phHal_eJewel_ReadAll:
952 #else
953     case phHal_eJewelCmdListJewelReadAll:
954 #endif
955 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
956 
957 #ifdef TOPAZ_RAW_SUPPORT
958         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
959         /*Copy command to  Send Buffer*/
960         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_READALL;
961         index ++;
962 
963         /*Copy 0x00 to Send Buffer*/
964         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00;
965         index ++;
966         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00;
967         index ++;
968 
969         /*Copy UID of the tag to  Send Buffer*/
970         (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]),
971         &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid),
972         TOPAZ_UID_LENGTH_FOR_READ_WRITE);
973 
974         index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
975 
976         /* Update the length of the command buffer*/
977         NdefMap->SendLength = index;
978 #else
979        /* For READ ID and READ ALL, send length is 0 */
980         NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0;
981 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
982         break;
983 
984 #ifdef TOPAZ_RAW_SUPPORT
985     case PH_FRINFC_TOPAZ_CMD_READ:
986 #else
987 #ifdef PH_HAL4_ENABLE
988     case phHal_eJewel_Read1:
989 #else
990     case phHal_eJewelCmdListJewelRead1:
991 #endif
992 
993 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
994 
995 #ifdef TOPAZ_RAW_SUPPORT
996         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
997         /*Copy command to  Send Buffer*/
998         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_READ;
999         index ++;
1000 
1001         /*Copy Address to  Send Buffer*/
1002         /* Calculate send length
1003         7 | 6   5   4   3 | 2   1   0 |
1004         |    block no   |  byte no  |
1005         */
1006         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] =
1007                 (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
1008                 ByteNo);
1009         index ++;
1010         /*Copy 0x00 to  Send Buffer*/
1011         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00;
1012         index ++;
1013 
1014         /*Copy UID of the tag to  Send Buffer*/
1015         (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]),
1016         &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid),
1017         TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1018         index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1019 
1020         /* Update the length of the command buffer*/
1021         NdefMap->SendLength = index;
1022 #else
1023         /* Calculate send length
1024         7 | 6   5   4   3 | 2   1   0 |
1025         |    block no   |  byte no  |
1026         */
1027         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] =
1028                 (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
1029                 ByteNo);
1030         NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL1;
1031 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
1032 
1033         break;
1034 #ifdef TOPAZ_RAW_SUPPORT
1035 #else
1036 #ifdef PH_HAL4_ENABLE
1037     case phHal_eJewel_Read:
1038         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = 0x00;
1039         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00;
1040         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 104;
1041         NdefMap->SendLength = 3;
1042     break;
1043 #endif
1044 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
1045 
1046     default:
1047         Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1048                             NFCSTATUS_INVALID_DEVICE_REQUEST);
1049     }
1050 
1051     if(Result == NFCSTATUS_SUCCESS)
1052     {
1053         /* Call the Overlapped HAL Transceive function */
1054         Result = phFriNfc_OvrHal_Transceive(    NdefMap->LowerDevice,
1055                                                 &NdefMap->MapCompletionInfo,
1056                                                 NdefMap->psRemoteDevInfo,
1057                                                 NdefMap->Cmd,
1058                                                 &NdefMap->psDepAdditionalInfo,
1059                                                 NdefMap->SendRecvBuf,
1060                                                 NdefMap->SendLength,
1061                                                 NdefMap->SendRecvBuf,
1062                                                 NdefMap->SendRecvLength);
1063     }
1064     return Result;
1065 }
1066 
phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t * NdefMap,uint16_t BlockNo,uint16_t ByteNo,uint8_t ByteVal)1067 static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap,
1068                                         uint16_t             BlockNo,
1069                                         uint16_t             ByteNo,
1070                                         uint8_t              ByteVal
1071                                         )
1072 {
1073     NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1074     uint8_t     index = 0;
1075 
1076 
1077     PHNFC_UNUSED_VARIABLE(ByteVal);
1078     /* set the data for additional data exchange*/
1079     NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
1080     NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
1081     NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
1082 
1083     NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process;
1084     NdefMap->MapCompletionInfo.Context = NdefMap;
1085 
1086     *NdefMap->SendRecvLength = NdefMap->TempReceiveLength;
1087     /* Command used to write 1 byte */
1088 #ifdef TOPAZ_RAW_SUPPORT
1089     NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
1090 #else
1091 #ifdef PH_HAL4_ENABLE
1092     NdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
1093 #else
1094     NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelWriteErase1;
1095 #endif
1096 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
1097 
1098 #ifdef TOPAZ_RAW_SUPPORT
1099     /*Copy command to Send Buffer*/
1100     NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]  = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
1101     index ++;
1102 
1103     /*Copy Address to  Send Buffer*/
1104     /* Calculate send length
1105     7 | 6   5   4   3 | 2   1   0 |
1106     |    block no   |  byte no  |
1107     */
1108     NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] =
1109             (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
1110             ByteNo);
1111     index ++;
1112     /*Copy Data byte to Send Buffer*/
1113     NdefMap->SendRecvBuf[index] = ByteVal;
1114     index ++;
1115 
1116     /*Copy UID of the tag to  Send Buffer*/
1117     (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]),
1118       &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid),
1119       TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1120     index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE);
1121 
1122     /* Update the length of the command buffer*/
1123     NdefMap->SendLength = index;
1124 
1125 #else
1126     /* Depending on the jewel command, the send length is decided */
1127     /* Calculate send length
1128     7 | 6   5   4   3 | 2   1   0 |
1129     |    block no   |  byte no  |
1130     */
1131     NdefMap->SendRecvBuf[index] =
1132                         (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) +
1133                         ByteNo);
1134     index ++;
1135     NdefMap->SendRecvBuf[index] = ByteVal;
1136     index ++;
1137     NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL2;
1138 
1139 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
1140 
1141     /* Call the Overlapped HAL Transceive function */
1142     Result = phFriNfc_OvrHal_Transceive(    NdefMap->LowerDevice,
1143                                             &NdefMap->MapCompletionInfo,
1144                                             NdefMap->psRemoteDevInfo,
1145                                             NdefMap->Cmd,
1146                                             &NdefMap->psDepAdditionalInfo,
1147                                             NdefMap->SendRecvBuf,
1148                                             NdefMap->SendLength,
1149                                             NdefMap->SendRecvBuf,
1150                                             NdefMap->SendRecvLength);
1151 
1152     return Result;
1153 }
1154 
phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t * NdefMap)1155 static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap)
1156 {
1157     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1158         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1159 
1160     if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] &
1161         PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) &&
1162         (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL6))
1163     {
1164         /* Copy UID to the context, Used when the READ ALL command is used */
1165         (void)memcpy(NdefMap->TopazContainer.UID,
1166             &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2],
1167             PH_FRINFC_TOPAZ_VAL4);
1168 
1169         /* State has to be changed */
1170         NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL;
1171         /* Topaz command = READALL */
1172 #ifdef TOPAZ_RAW_SUPPORT
1173         NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
1174         NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL;
1175 #else
1176 #ifdef PH_HAL4_ENABLE
1177         NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll;
1178 #else
1179         NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll;
1180 #endif
1181 #endif /* #ifdef TOPAZ_RAW_SUPPORT */
1182 
1183         /* Read all bytes from the card */
1184         Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock,
1185             NdefMap->TopazContainer.ByteNumber);
1186     }
1187 
1188     return Result;
1189 }
1190 
phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t * NdefMap)1191 static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap)
1192 {
1193     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1194         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1195     int32_t     memcompare = PH_FRINFC_TOPAZ_VAL0;
1196 
1197     /* Compare the UID of READ ALL command with the stored UID */
1198 #ifdef PH_HAL4_ENABLE
1199     if ((NdefMap->TopazContainer.UID[0] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2]) &&
1200         (NdefMap->TopazContainer.UID[1] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 1]) &&
1201         (NdefMap->TopazContainer.UID[2] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 2]) &&
1202         (NdefMap->TopazContainer.UID[3] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 3]))
1203     {
1204         memcompare = PH_FRINFC_TOPAZ_VAL0;
1205     }
1206     else
1207     {
1208         memcompare = PH_FRINFC_TOPAZ_VAL1;
1209     }
1210 #else
1211     memcompare = memcmp(NdefMap->TopazContainer.UID,
1212         &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2],
1213         PH_FRINFC_TOPAZ_VAL4);
1214 #endif /* #ifdef PH_HAL4_ENABLE */
1215 
1216     if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] &
1217         PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) &&
1218         (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_READALL_RESP) &&
1219         (memcompare == PH_FRINFC_TOPAZ_VAL0))
1220     {
1221         /* Copy 96 bytes from the read/write memory space */
1222         (void)memcpy(NdefMap->TopazContainer.ReadBuffer,
1223             &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL10],
1224             PH_FRINFC_TOPAZ_TOTAL_RWBYTES);
1225 
1226         /* Check the lock bits and set the card state */
1227         phFriNfc_Tpz_H_ChkLockBits(NdefMap);
1228 
1229         Result = phFriNfc_Tpz_H_CallNxtOp(NdefMap);
1230     }
1231     return Result;
1232 }
1233 
phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t * NdefMap)1234 static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap)
1235 {
1236     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1237         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1238     /* Depending on the operation (check, read or write ndef), process the
1239     read data */
1240     switch(NdefMap->PrevOperation)
1241     {
1242     case PH_FRINFC_NDEFMAP_CHECK_OPE:
1243         /* Check the capabilty container values, according
1244         to the spec */
1245         Result = phFriNfc_Tpz_H_ChkCCinChkNdef(NdefMap);
1246 
1247         if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID)
1248         {
1249             /* Check the spec version */
1250             Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap,
1251                 NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]);
1252             /*  Check the CC header size: Only valid ones are
1253             0x0C for 96 bytes. */
1254             if ((Result == NFCSTATUS_SUCCESS) &&
1255                 ( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] <=
1256                 PH_FRINFC_TOPAZ_CC_BYTE2_MAX))
1257             {
1258                 Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap);
1259                 /* As there is possibility of either having or not having TLV in
1260                 Topaz, no need to send the Actual status to the context*/
1261                 Result = NFCSTATUS_SUCCESS;
1262             }
1263         }
1264         else
1265         {
1266             Result = NFCSTATUS_SUCCESS;
1267             NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED;
1268             NdefMap->CardMemSize =
1269             NdefMap->TopazContainer.RemainingSize = (uint16_t)
1270                         /*
1271                         4 is decremented from the max size because of the 4 CC bytes
1272                         2 is decremented because of the NDEF TLV T and L byte
1273                         to get the actual data size
1274                         */
1275                         (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4 -
1276                         PH_FRINFC_TOPAZ_VAL2);
1277         }
1278         break;
1279 
1280     case PH_FRINFC_NDEFMAP_READ_OPE:
1281         /* Check the capabilty container values, according
1282         to the spec */
1283         Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap);
1284 
1285         /* If success, find the ndef TLV */
1286         Result = ((Result != NFCSTATUS_SUCCESS)?
1287                 (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1288                 NFCSTATUS_INVALID_FORMAT)):
1289                 phFriNfc_Tpz_H_findNDEFTLV(NdefMap));
1290 
1291         if(Result == NFCSTATUS_SUCCESS)
1292         {
1293             NdefMap->TopazContainer.ByteNumber += PH_FRINFC_TOPAZ_VAL2;
1294             /* If success, copy the read bytes to the user buffer */
1295             Result = phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap);
1296         }
1297         break;
1298 
1299     case PH_FRINFC_NDEFMAP_WRITE_OPE:
1300     default:
1301         if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) ||
1302             (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED))
1303         {
1304             /* Check the capabilty container values, according
1305             to the spec */
1306             Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap);
1307             if(Result == NFCSTATUS_SUCCESS)
1308             {
1309                 /* Find the NDEF TLV */
1310                 Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap);
1311 
1312                 /* Write the TLV */
1313                 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV;
1314             }
1315             else
1316             {
1317                 NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4;
1318                 NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1;
1319                 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4;
1320                 /* Write the TLV */
1321                 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE0;
1322             }
1323             /* Write CC bytes */
1324             Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1325         }
1326         break;
1327     }
1328     return Result;
1329 }
1330 
phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t * NdefMap)1331 static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap)
1332 {
1333     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1334         NFCSTATUS_NO_NDEF_SUPPORT);
1335 
1336     if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] ==
1337         PH_FRINFC_TOPAZ_CC_BYTE0)
1338     {
1339         /* Check the spec version */
1340         Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap,
1341             NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]);
1342         /*  Check the CC header size: Only valid ones are
1343         0x0C for 96 bytes. */
1344         Result = ((( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] >
1345                     PH_FRINFC_TOPAZ_CC_BYTE2_MAX) || (Result !=
1346                     NFCSTATUS_SUCCESS))?
1347                     (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1348                     NFCSTATUS_EOF_NDEF_CONTAINER_REACHED)):
1349                     Result);
1350 
1351         /* Get the read/write card memory size */
1352         NdefMap->TopazContainer.RemainingSize =
1353                 NdefMap->CardMemSize = ((Result == NFCSTATUS_SUCCESS)?
1354                 (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4):
1355                 NdefMap->CardMemSize);
1356 
1357         /* if the call is from write ndef then check for read write access */
1358         if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) &&
1359             (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] !=
1360             PH_FRINFC_TOPAZ_CC_BYTE3_RW) && (Result == NFCSTATUS_SUCCESS)))
1361         {
1362             Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1363                                 NFCSTATUS_INVALID_FORMAT));
1364         }
1365 
1366         /* if the call is from read ndef then check for read only or read write access */
1367         if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) &&
1368             ((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] !=
1369             PH_FRINFC_TOPAZ_CC_BYTE3_RW) &&
1370             (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] !=
1371             PH_FRINFC_TOPAZ_CC_BYTE3_RO))&& (Result == NFCSTATUS_SUCCESS)))
1372         {
1373             Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1374                                 NFCSTATUS_INVALID_FORMAT));
1375         }
1376     }
1377     return Result;
1378 }
1379 
phFriNfc_Tpz_H_ChkSpcVer(phFriNfc_NdefMap_t * NdefMap,uint8_t VersionNo)1380 extern NFCSTATUS phFriNfc_Tpz_H_ChkSpcVer( phFriNfc_NdefMap_t  *NdefMap,
1381                                           uint8_t             VersionNo)
1382 {
1383     NFCSTATUS Result = NFCSTATUS_SUCCESS;
1384     uint8_t TagVerNo = VersionNo;
1385 
1386     /* To remove "warning (VS C4100) : unreferenced formal parameter" */
1387     PHNFC_UNUSED_VARIABLE(NdefMap);
1388 
1389     if ( TagVerNo == 0 )
1390     {
1391         /*Return Status Error � Invalid Format�*/
1392         Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT);
1393     }
1394     else
1395     {
1396         /* calculate the major and minor version number of T3VerNo */
1397         if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM ==
1398             PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&&
1399             ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM >=
1400             PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) ||
1401             (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM ==
1402             PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&&
1403             ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM <
1404             PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) )))
1405         {
1406             Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS);
1407         }
1408         else
1409         {
1410             if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM <
1411                 PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) ||
1412                 ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM >
1413                 PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo)))
1414             {
1415                 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT);
1416             }
1417         }
1418     }
1419     return Result;
1420 }
1421 
phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t * NdefMap)1422 static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap)
1423 {
1424     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1425         NFCSTATUS_NO_NDEF_SUPPORT);
1426     uint8_t     index = PH_FRINFC_TOPAZ_VAL4;
1427 
1428     /* If remaining size is less than 3 then, there cant be any
1429     TLV present in the card */
1430     while((index < PH_FRINFC_TOPAZ_TOTAL_RWBYTES) &&
1431         (NdefMap->TopazContainer.RemainingSize >= PH_FRINFC_TOPAZ_VAL3))
1432     {
1433         switch(NdefMap->TopazContainer.ReadBuffer[index])
1434         {
1435         case PH_FRINFC_TOPAZ_NDEF_T:
1436             /* To get the length field of the TLV */
1437             index++;
1438             /* Type and length are not data bytes, so to know the exact
1439             remaining size in the card, the below operation is done */
1440             NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2;
1441             /* Set the card state depending on the L value */
1442             Result = phFriNfc_MapTool_SetCardState(NdefMap,
1443                 (uint32_t)NdefMap->TopazContainer.ReadBuffer[index]);
1444             /* Check the TLV is correct */
1445             if((NdefMap->TopazContainer.ReadBuffer[index] >
1446                 NdefMap->TopazContainer.RemainingSize) ||
1447                 ((NdefMap->TopazContainer.ReadBuffer[index] ==
1448                 PH_FRINFC_TOPAZ_VAL0) && (NdefMap->PrevOperation ==
1449                 PH_FRINFC_NDEFMAP_READ_OPE)) || (Result != NFCSTATUS_SUCCESS))
1450             {
1451                 /* L field value cant be greater than the remaining size, so error */
1452                 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1453                                     NFCSTATUS_NO_NDEF_SUPPORT);
1454                 /* To break out of the loop */
1455                 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1456             }
1457             else
1458             {
1459                 /* So remaining size also changes, according to the position of NDEF TLV  */
1460                 NdefMap->TLVStruct.BytesRemainLinTLV =
1461                     NdefMap->TopazContainer.ReadBuffer[index];
1462 
1463                 /* Get the byte number */
1464                 NdefMap->TLVStruct.NdefTLVByte = (uint16_t)((index - PH_FRINFC_TOPAZ_VAL1) %
1465                                                     PH_FRINFC_TOPAZ_VAL8);
1466                 /* Get the block number */
1467                 NdefMap->TLVStruct.NdefTLVBlock = (uint8_t)(((index - PH_FRINFC_TOPAZ_VAL1) /
1468                                                     PH_FRINFC_TOPAZ_VAL8) +
1469                                                     PH_FRINFC_TOPAZ_VAL1);
1470                 /* TLV found flag is set */
1471                 NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_TOPAZ_FLAG1;
1472                 /* To know the position of V field in the TLV */
1473                 NdefMap->TopazContainer.ByteNumber = (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock - 1) * 8) +
1474                                                     NdefMap->TLVStruct.NdefTLVByte);
1475                 /* To break out of the loop */
1476                 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1477                 Result = NFCSTATUS_SUCCESS;
1478             }
1479             break;
1480 
1481         case PH_FRINFC_TOPAZ_NULL_T:
1482             /* Null TLV, Skip the TLV */
1483             NdefMap->TopazContainer.RemainingSize--;
1484             index++;
1485             break;
1486 
1487         case PH_FRINFC_TOPAZ_TERM_T:
1488             /* No more TLV present in the card, so error */
1489             index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1490             Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1491                                 NFCSTATUS_NO_NDEF_SUPPORT);
1492             break;
1493 
1494         default:
1495             /* Go till the length field of the TLV */
1496             index++;
1497             /* Type and length is not the data, so to know the exact
1498             remaining size in the card, the below operation is done */
1499             NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2;
1500             if(NdefMap->TopazContainer.ReadBuffer[index] >
1501                 NdefMap->TopazContainer.RemainingSize)
1502             {
1503                 /* L field value cant be greater than the remaining size, so error */
1504                 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES;
1505                 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1506                                     NFCSTATUS_NO_NDEF_SUPPORT);
1507             }
1508             else
1509             {
1510                 /* Remaining size of the free space available in the card changes,
1511                 according to the position of NDEF TLV */
1512                 NdefMap->TopazContainer.RemainingSize =
1513                     NdefMap->TopazContainer.RemainingSize -
1514                     NdefMap->TopazContainer.ReadBuffer[index];
1515 
1516                 /* Get the position of the next TLV */
1517                 index = (uint8_t)(index +
1518                     (NdefMap->TopazContainer.ReadBuffer[index] +
1519                      PH_FRINFC_TOPAZ_VAL1));
1520             }
1521             break;
1522         }
1523     }
1524 
1525     /* If no Ndef TLV found and operation done is read */
1526     if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) &&
1527         (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))
1528     {
1529         Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1530                             NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
1531     }
1532     if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) &&
1533         ((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) ||
1534         (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_CHECK_OPE)))
1535     {
1536         NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4;
1537         NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1;
1538         NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4;
1539         NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_TOTAL_RWBYTES1;
1540     }
1541     return Result;
1542 }
1543 
phFriNfc_Tpz_H_CpDataToUsrBuf(phFriNfc_NdefMap_t * NdefMap)1544 static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf(phFriNfc_NdefMap_t  *NdefMap)
1545 {
1546     NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1547 
1548     /* Check the the TLV size and the user size */
1549     if(NdefMap->ApduBufferSize >=
1550         NdefMap->TLVStruct.BytesRemainLinTLV)
1551     {
1552         /* Copy the read bytes to user buffer till the value (V)
1553         of TLV ends */
1554         (void)memcpy(NdefMap->ApduBuffer,
1555             &(NdefMap->TopazContainer.ReadBuffer[
1556                 NdefMap->TopazContainer.ByteNumber]),
1557                     NdefMap->TLVStruct.BytesRemainLinTLV);
1558 
1559                 /* Update the number of read bytes to the user */
1560                 *(NdefMap->NumOfBytesRead) =
1561                     NdefMap->TLVStruct.BytesRemainLinTLV;
1562                 /* There is no byte to read */
1563                 NdefMap->TopazContainer.ByteNumber =
1564                                                     PH_FRINFC_TOPAZ_VAL0;
1565                 /* No further read is possible */
1566                 NdefMap->TopazContainer.ReadWriteCompleteFlag =
1567                                                     PH_FRINFC_TOPAZ_FLAG1;
1568                 /* Remaining size in the card can be greater than length field in
1569                 the TLV */
1570                 NdefMap->TopazContainer.RemainingSize =
1571                     NdefMap->TopazContainer.RemainingSize -
1572                                         NdefMap->TLVStruct.BytesRemainLinTLV;
1573                 /* TLV has been completely read, no more bytes to read */
1574                 NdefMap->TLVStruct.BytesRemainLinTLV =
1575                                                     PH_FRINFC_TOPAZ_VAL0;
1576     }
1577     else
1578     {
1579         /* Copy read bytes till the user buffer size */
1580         (void)memcpy(NdefMap->ApduBuffer,
1581                     &(NdefMap->TopazContainer.ReadBuffer[
1582                     NdefMap->TopazContainer.ByteNumber]),
1583                     NdefMap->ApduBufferSize);
1584 
1585         /* Update the number of read bytes to the user */
1586         *(NdefMap->NumOfBytesRead) =
1587             NdefMap->ApduBufferSize;
1588         /* Get the next byte number to read */
1589         NdefMap->TopazContainer.ByteNumber =
1590             (uint8_t)(NdefMap->TopazContainer.ByteNumber +
1591                       NdefMap->ApduBufferSize);
1592         /* Free space left in the card */
1593         NdefMap->TopazContainer.RemainingSize
1594             = NdefMap->TopazContainer.RemainingSize
1595                   - (uint16_t)NdefMap->ApduBufferSize;
1596         /* Bytes left in the TLV */
1597         NdefMap->TLVStruct.BytesRemainLinTLV =
1598             NdefMap->TLVStruct.BytesRemainLinTLV -
1599                    (uint16_t)NdefMap->ApduBufferSize;
1600     }
1601     return Result;
1602 }
1603 
phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t * NdefMap)1604 static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap)
1605 {
1606     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1607         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1608     uint8_t     BlockNo = PH_FRINFC_TOPAZ_VAL0,
1609         ByteNo = PH_FRINFC_TOPAZ_VAL0;
1610 
1611     if((NdefMap->TopazContainer.InternalState ==
1612         PH_FRINFC_TOPAZ_WR_NMN_0) &&
1613         (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1614         PH_FRINFC_TOPAZ_VAL0) &&
1615         (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1616     {
1617         NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV;
1618         /* Get the L field of the TLV block */
1619         BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) >
1620                             PH_FRINFC_TOPAZ_VAL7)?
1621                             (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_TOPAZ_VAL1):
1622                             NdefMap->TLVStruct.NdefTLVBlock);
1623         /* Get the L byte */
1624         ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) %
1625                                 PH_FRINFC_TOPAZ_VAL8);
1626 
1627 
1628         /* Here the NMN is written 0, so internal state is used */
1629         NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV_0;
1630         /* Write the length value = 0x00 , Write L field of TLV  = 0  inside this*/
1631         Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,
1632                                         PH_FRINFC_TOPAZ_VAL0);
1633     }
1634     else
1635     {
1636         if((NdefMap->TopazContainer.InternalState ==
1637             PH_FRINFC_TOPAZ_WR_NMN_E1) &&
1638             (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1639             PH_FRINFC_TOPAZ_CC_BYTE0) &&
1640             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1641         {
1642             /* Card state is initialised or invalid */
1643             NdefMap->CardState = (uint8_t)((NdefMap->CardState ==
1644                                     PH_NDEFMAP_CARD_STATE_INITIALIZED)?
1645                                     PH_NDEFMAP_CARD_STATE_READ_WRITE:
1646                                     NdefMap->CardState);
1647             /* update the length to the user */
1648             *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex;
1649             Result = NFCSTATUS_SUCCESS;
1650         }
1651     }
1652     return Result;
1653 }
1654 
phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t * NdefMap)1655 static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap)
1656 {
1657     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1658         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1659     if((NdefMap->TopazContainer.InternalState ==
1660         PH_FRINFC_TOPAZ_WR_L_TLV_0) &&
1661         (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1662         PH_FRINFC_TOPAZ_VAL0) &&
1663         (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1664     {
1665         /* state is writing user data to the card */
1666         NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
1667 
1668         NdefMap->TopazContainer.ByteNumber++;
1669         /* Check the byte number */
1670         phFriNfc_Tpz_H_BlkChk(NdefMap);
1671 
1672         /* Write data to the specified location */
1673         /* Write the data to the card from the user buffer */
1674         Result = phFriNfc_Tpz_H_WrAByte( NdefMap,
1675                                         NdefMap->TopazContainer.CurrentBlock,
1676                                         NdefMap->TopazContainer.ByteNumber,
1677                                         NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]
1678                                         );
1679     }
1680     else
1681     {
1682         if((NdefMap->TopazContainer.InternalState ==
1683             PH_FRINFC_TOPAZ_WR_L_TLV) &&
1684             (((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) &&
1685             (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1686             NdefMap->ApduBuffIndex)) ||
1687             ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) &&
1688             (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1689             (NdefMap->ApduBuffIndex + NdefMap->TLVStruct.BytesRemainLinTLV)))) &&
1690             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1691         {
1692             /* Update the L value in the context */
1693             NdefMap->TLVStruct.BytesRemainLinTLV =
1694                 ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
1695                 NdefMap->ApduBuffIndex:
1696             (NdefMap->TLVStruct.BytesRemainLinTLV + NdefMap->ApduBuffIndex));
1697 
1698             /* Write 0xE1 in block number = 1 and byte number = 0 */
1699             Result = phFriNfc_Tpz_H_WrByte0ValE1(NdefMap);
1700         }
1701     }
1702     return Result;
1703 }
1704 
phFriNfc_Tpz_H_ProWrUsrData(phFriNfc_NdefMap_t * NdefMap)1705 static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData(phFriNfc_NdefMap_t *NdefMap)
1706 {
1707     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1708         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1709     /* send buffer should be equal to receive buffer */
1710     if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1711         NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]) &&
1712         (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1713     {
1714         /* Increment the index */
1715         NdefMap->ApduBuffIndex += PH_FRINFC_TOPAZ_VAL1;
1716 
1717         /* Remaining space left in the card is less by one */
1718         NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL1;
1719 
1720         /* Increment the byte number */
1721         NdefMap->TopazContainer.ByteNumber++;
1722 
1723         /* Check the block number */
1724         phFriNfc_Tpz_H_BlkChk(NdefMap);
1725 
1726         /* check for the user space or the card size */
1727         if((NdefMap->ApduBufferSize == NdefMap->ApduBuffIndex) ||
1728             (NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0))
1729         {
1730             /* Set write complete, if the end of card is reached */
1731             NdefMap->TopazContainer.ReadWriteCompleteFlag = (uint8_t)
1732                 ((NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)?
1733                 PH_FRINFC_TOPAZ_FLAG1:PH_FRINFC_TOPAZ_FLAG0);
1734 
1735             Result = phFriNfc_Tpz_H_WrLByte(NdefMap);
1736         }
1737         else
1738         {
1739             /* State is continued to be in write */
1740             NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
1741 
1742             /* Write the byte to the specified location , and Byte to write */
1743             Result = phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock,
1744                                             NdefMap->TopazContainer.ByteNumber,
1745                                             NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]
1746                                             );
1747         }
1748     }
1749     return Result;
1750 }
1751 
phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t * NdefMap)1752 static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t  *NdefMap)
1753 {
1754     NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1755     uint8_t     BlockNo = PH_FRINFC_TOPAZ_VAL0,
1756         ByteNo = PH_FRINFC_TOPAZ_VAL0;
1757     uint8_t TempByteVal = 0;
1758     BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte +
1759                             PH_FRINFC_TOPAZ_VAL1) >
1760                             PH_FRINFC_TOPAZ_VAL7)?
1761                             (NdefMap->TLVStruct.NdefTLVBlock +
1762                             PH_FRINFC_TOPAZ_VAL1):
1763     NdefMap->TLVStruct.NdefTLVBlock);
1764 
1765     ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte +
1766                         PH_FRINFC_TOPAZ_VAL1) % PH_FRINFC_TOPAZ_VAL8);
1767     /* Update L field */
1768     NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV;
1769     /* Internal state for write */
1770     NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV;
1771     /* Update the length field depending on the offset */
1772     TempByteVal = (uint8_t)
1773                     ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)?
1774                     NdefMap->ApduBuffIndex:
1775                     (NdefMap->ApduBuffIndex +
1776                     NdefMap->TLVStruct.BytesRemainLinTLV));
1777     /* Write the L field */
1778     Result = phFriNfc_Tpz_H_WrAByte(NdefMap, BlockNo, ByteNo,TempByteVal);
1779     return Result;
1780 }
1781 
phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t * NdefMap)1782 static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t   *NdefMap)
1783 {
1784     NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1785 
1786     /* Update L field */
1787     NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN;
1788     /* Internal state for writing 0xE1 */
1789     NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_E1;
1790     /* Update the length field depending on the offset */
1791     /* Write the L field */
1792     Result = phFriNfc_Tpz_H_WrAByte(NdefMap, PH_FRINFC_TOPAZ_VAL1,
1793                                     PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_CC_BYTE0);
1794     return Result;
1795 }
1796 
phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t * NdefMap,NFCSTATUS Status)1797 static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t  *NdefMap,
1798                                     NFCSTATUS           Status)
1799 {
1800     /* set the state back to the Reset_Init state*/
1801     NdefMap->State =  PH_FRINFC_NDEFMAP_STATE_RESET_INIT;
1802 
1803     /* set the completion routine*/
1804     NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex].
1805         CompletionRoutine(NdefMap->CompletionRoutine->Context, Status);
1806 }
1807 
phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t * NdefMap)1808 static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t  *NdefMap)
1809 {
1810     NdefMap->TopazContainer.CurrentBlock =
1811                     (uint8_t)((NdefMap->TopazContainer.ByteNumber >
1812                     PH_FRINFC_TOPAZ_VAL7)?
1813                     (NdefMap->TopazContainer.CurrentBlock +
1814                     PH_FRINFC_TOPAZ_VAL1):
1815                     NdefMap->TopazContainer.CurrentBlock);
1816 
1817     NdefMap->TopazContainer.ByteNumber = (uint8_t)(NdefMap->TopazContainer.ByteNumber %
1818                                         PH_FRINFC_TOPAZ_VAL8);
1819 }
1820 
phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t * NdefMap)1821 static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t  *NdefMap)
1822 {
1823     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1824                                     NFCSTATUS_NO_NDEF_SUPPORT);
1825 
1826     if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] ==
1827         PH_FRINFC_TOPAZ_CC_BYTE0)
1828     {
1829         /* Check the most significant nibble of byte 3 (RWA) = 0 */
1830         Result = (((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] &
1831                     PH_FRINFC_TOPAZ_BYTE3_MSB)== PH_FRINFC_TOPAZ_VAL0)?
1832                     NFCSTATUS_SUCCESS:
1833                     Result);
1834 
1835         /* Card size is initialised */
1836         NdefMap->CardMemSize = NdefMap->TopazContainer.RemainingSize =
1837                             ((Result == NFCSTATUS_SUCCESS)?
1838                             (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4):
1839                             NdefMap->CardMemSize);
1840     }
1841 
1842     if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY)
1843     {
1844         NdefMap->CardState = (uint8_t)((Result == NFCSTATUS_SUCCESS)?
1845                             PH_NDEFMAP_CARD_STATE_INITIALIZED:
1846                             PH_NDEFMAP_CARD_STATE_INVALID);
1847     }
1848 
1849     return Result;
1850 }
1851 
phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t * NdefMap)1852 static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t  *NdefMap)
1853 {
1854     /* Set the card state */
1855     NdefMap->CardState =  (uint8_t)
1856         (((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_0] ==
1857         PH_FRINFC_TOPAZ_LOCKBIT_BYTE114) &&
1858         ((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] ==
1859         PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_1) ||
1860         (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] ==
1861         PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_2)))?
1862         PH_NDEFMAP_CARD_STATE_READ_WRITE:
1863         PH_NDEFMAP_CARD_STATE_READ_ONLY);
1864 
1865     /* Set the card state from CC bytes */
1866     if (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE)
1867     {
1868         if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READWRITE)
1869         {
1870             NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE;
1871         }
1872         else if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READONLY)
1873         {
1874             NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY;
1875         }
1876         else
1877         {
1878             NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
1879         }
1880     }
1881 }
1882 
phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t * NdefMap)1883 static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t  *NdefMap)
1884 {
1885     NFCSTATUS   Result = NFCSTATUS_SUCCESS;
1886     uint8_t     ByteNo = PH_FRINFC_TOPAZ_VAL0,
1887         BlockNo = PH_FRINFC_TOPAZ_VAL0;
1888     uint8_t TempByteVal = 0;
1889     switch(NdefMap->TopazContainer.InternalState)
1890     {
1891     case PH_FRINFC_TOPAZ_WR_CC_BYTE0:
1892         /* To write the CC bytes */
1893         TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE0;
1894         ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL0;
1895         BlockNo = PH_FRINFC_TOPAZ_VAL1;
1896         break;
1897 
1898     case PH_FRINFC_TOPAZ_WR_CC_BYTE1:
1899         /* To write the CC bytes */
1900         TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE1;
1901         ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL1;
1902         BlockNo = PH_FRINFC_TOPAZ_VAL1;
1903         break;
1904 
1905     case PH_FRINFC_TOPAZ_WR_CC_BYTE2:
1906         /* To write the CC bytes */
1907         TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE2_MAX;
1908         ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL2;
1909         BlockNo = PH_FRINFC_TOPAZ_VAL1;
1910         break;
1911 
1912     case PH_FRINFC_TOPAZ_WR_CC_BYTE3:
1913         /* To write the CC bytes */
1914         TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE3_RW;
1915         ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL3;
1916         BlockNo = PH_FRINFC_TOPAZ_VAL1;
1917         break;
1918 
1919     case PH_FRINFC_TOPAZ_WR_T_OF_TLV:
1920     default:
1921         /* To write the NDEF TLV (if not present) */
1922         TempByteVal = PH_FRINFC_TOPAZ_NDEF_T;
1923         ByteNo = (uint8_t)NdefMap->TLVStruct.NdefTLVByte;
1924         BlockNo = NdefMap->TLVStruct.NdefTLVBlock;
1925         break;
1926     }
1927     NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV;
1928     Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,TempByteVal);
1929     return Result;
1930 }
1931 
phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t * NdefMap)1932 static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t  *NdefMap)
1933 {
1934     NFCSTATUS   Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
1935         NFCSTATUS_INVALID_RECEIVE_LENGTH);
1936     switch(NdefMap->TopazContainer.InternalState)
1937     {
1938     case PH_FRINFC_TOPAZ_WR_CC_BYTE0:
1939         /* Process the CC byte */
1940         /* Check the response */
1941         if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1942             PH_FRINFC_TOPAZ_CC_BYTE0) &&
1943             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1944         {
1945             NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE1;
1946             Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1947         }
1948         break;
1949 
1950     case PH_FRINFC_TOPAZ_WR_CC_BYTE1:
1951         /* Process the CC byte */
1952         /* Check the response */
1953         if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1954             PH_FRINFC_TOPAZ_CC_BYTE1) &&
1955             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1956         {
1957             NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE2;
1958             Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1959         }
1960         break;
1961 
1962     case PH_FRINFC_TOPAZ_WR_CC_BYTE2:
1963         /* Process the CC byte */
1964         /* Check the response */
1965         if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1966             PH_FRINFC_TOPAZ_CC_BYTE2_MAX) &&
1967             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1968         {
1969             NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE3;
1970             Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1971         }
1972         break;
1973 
1974     case PH_FRINFC_TOPAZ_WR_CC_BYTE3:
1975         /* Process the CC byte */
1976         /* Check the response */
1977         if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1978             PH_FRINFC_TOPAZ_CC_BYTE3_RW) &&
1979             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1980         {
1981             NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV;
1982             Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap);
1983         }
1984         break;
1985 
1986     case PH_FRINFC_TOPAZ_WR_T_OF_TLV:
1987     default:
1988         /* Check the response */
1989         if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] ==
1990             PH_FRINFC_TOPAZ_NDEF_T) &&
1991             (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1))
1992         {
1993             /* Increment the Byte Number */
1994             NdefMap->TopazContainer.ByteNumber++;
1995             /* Check the block and byte number */
1996             phFriNfc_Tpz_H_BlkChk(NdefMap);
1997             /* Process the T of NDEF TLV */
1998             NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN;
1999 
2000             /* Here the NMN is written 0, so internal state is used */
2001             NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_0;
2002 
2003             /*Inside this call Write NMN (block number 1 and byte number 0) = 0 */
2004             Result = phFriNfc_Tpz_H_WrAByte( NdefMap, PH_FRINFC_TOPAZ_VAL1,
2005                 PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_VAL0);
2006         }
2007         break;
2008     }
2009     return Result;
2010 }
2011 
2012 #ifdef UNIT_TEST
2013 #include <phUnitTestNfc_Topaz_static.c>
2014 #endif
2015 
2016 #endif  /* PH_FRINFC_MAP_TOPAZ_DISABLED */
2017