rw_t2t_ndef.c revision c11a054fc2855196292b062a843321121b591cc0
1/******************************************************************************
2 *
3 *  Copyright (C) 2010-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  This file contains the implementation for Type 2 tag NDEF operation in
22 *  Reader/Writer mode.
23 *
24 ******************************************************************************/
25#include <string.h>
26#include "nfc_target.h"
27
28#if (NFC_INCLUDED == TRUE)
29#include "nfc_api.h"
30#include "nci_hmsgs.h"
31#include "rw_api.h"
32#include "rw_int.h"
33#include "nfc_int.h"
34#include "gki.h"
35
36#if (defined (RW_NDEF_INCLUDED) && (RW_NDEF_INCLUDED == TRUE))
37
38/* Local static functions */
39static void rw_t2t_handle_cc_read_rsp (void);
40static void rw_t2t_handle_lock_read_rsp (UINT8 *p_data);
41static void rw_t2t_handle_tlv_detect_rsp (UINT8 *p_data);
42static void rw_t2t_handle_ndef_read_rsp (UINT8 *p_data);
43static void rw_t2t_handle_ndef_write_rsp (UINT8 *p_data);
44static void rw_t2t_handle_format_tag_rsp (UINT8 *p_data);
45static void rw_t2t_handle_config_tag_readonly (UINT8 *p_data);
46static UINT8 rw_t2t_get_tag_size (UINT8 *p_data);
47static void rw_t2t_extract_default_locks_info (void);
48static void rw_t2t_update_cb (UINT16 block, UINT8 *p_write_block, BOOLEAN b_update_len);
49static UINT8 rw_t2t_get_ndef_flags (void);
50static UINT16 rw_t2t_get_ndef_max_size (void);
51static tNFC_STATUS rw_t2t_read_locks (void);
52static tNFC_STATUS rw_t2t_read_ndef_last_block (void);
53static void rw_t2t_update_attributes (void);
54static void rw_t2t_update_lock_attributes (void);
55static BOOLEAN rw_t2t_is_lock_res_byte (UINT16 index);
56static BOOLEAN rw_t2t_is_read_only_byte (UINT16 index);
57static tNFC_STATUS rw_t2t_write_ndef_first_block (UINT16 msg_len, BOOLEAN b_update_len);
58static tNFC_STATUS rw_t2t_write_ndef_next_block (UINT16 block, UINT16 msg_len, BOOLEAN b_update_len);
59static tNFC_STATUS rw_t2t_read_ndef_next_block (UINT16 block);
60static tNFC_STATUS rw_t2t_add_terminator_tlv (void);
61static BOOLEAN rw_t2t_is_read_before_write_block (UINT16 block, UINT16 *p_block_to_read);
62static tNFC_STATUS rw_t2t_set_cc (UINT8 tms);
63static tNFC_STATUS rw_t2t_set_lock_tlv (UINT16 addr, UINT8 num_dyn_lock_bits, UINT16 locked_area_size);
64static tNFC_STATUS rw_t2t_format_tag (void);
65static tNFC_STATUS rw_t2t_soft_lock_tag (void);
66static tNFC_STATUS rw_t2t_set_dynamic_lock_bits (UINT8 *p_data);
67static void rw_t2t_ntf_tlv_detect_complete (tNFC_STATUS status);
68
69const UINT8 rw_t2t_mask_bits[8] =
70{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
71
72/*******************************************************************************
73**
74** Function         rw_t2t_handle_rsp
75**
76** Description      This function handles response to command sent during
77**                  NDEF and other tlv operation
78**
79** Returns          None
80**
81*******************************************************************************/
82void rw_t2t_handle_rsp (UINT8 *p_data)
83{
84    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
85
86    if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC)
87    {
88        p_t2t->b_read_hdr = TRUE;
89        memcpy (p_t2t->tag_hdr,  p_data, T2T_READ_DATA_LEN);
90
91        /* On Ultralight - C tag, if CC is corrupt, correct it */
92        if (  (p_t2t->tag_hdr[0] == TAG_MIFARE_MID)
93            &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] >= T2T_INVALID_CC_TMS_VAL0)
94            &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] <= T2T_INVALID_CC_TMS_VAL1)  )
95        {
96            p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] = T2T_CC2_TMS_MULC;
97        }
98    }
99
100    switch (p_t2t->state)
101    {
102    case RW_T2T_STATE_DETECT_TLV:
103        if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV)
104        {
105            if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC)
106            {
107                rw_t2t_handle_cc_read_rsp ();
108            }
109            else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS)
110            {
111                rw_t2t_handle_lock_read_rsp (p_data);
112            }
113            else
114            {
115                rw_t2t_handle_tlv_detect_rsp (p_data);
116            }
117        }
118        else if (p_t2t->tlv_detect == TAG_NDEF_TLV)
119        {
120            if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC)
121            {
122                if (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] == T2T_CC0_NMN)
123                {
124                    rw_t2t_handle_cc_read_rsp ();
125                }
126                else
127                {
128                    RW_TRACE_WARNING3 ("NDEF Detection failed!, CC[0]: 0x%02x, CC[1]: 0x%02x, CC[3]: 0x%02x", p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE], p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
129                    rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_FAILED);
130                }
131            }
132            else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS)
133            {
134                rw_t2t_handle_lock_read_rsp (p_data);
135            }
136            else
137            {
138                rw_t2t_handle_tlv_detect_rsp (p_data);
139            }
140        }
141        else
142        {
143            if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC)
144            {
145                rw_t2t_handle_cc_read_rsp ();
146            }
147            else
148            {
149                rw_t2t_handle_tlv_detect_rsp (p_data);
150            }
151        }
152        break;
153
154    case RW_T2T_STATE_SET_TAG_RO:
155        rw_t2t_handle_config_tag_readonly (p_data);
156        break;
157
158    case RW_T2T_STATE_FORMAT_TAG:
159        rw_t2t_handle_format_tag_rsp (p_data);
160        break;
161
162    case RW_T2T_STATE_READ_NDEF:
163        rw_t2t_handle_ndef_read_rsp (p_data);
164        break;
165
166    case RW_T2T_STATE_WRITE_NDEF:
167        rw_t2t_handle_ndef_write_rsp (p_data);
168        break;
169    }
170}
171
172/*******************************************************************************
173**
174** Function         rw_t2t_info_to_event
175**
176** Description      This function returns RW event code based on the current state
177**
178** Returns          RW event code
179**
180*******************************************************************************/
181tRW_EVENT rw_t2t_info_to_event (const tT2T_CMD_RSP_INFO *p_info)
182{
183    tRW_EVENT   rw_event;
184    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
185
186    switch (p_t2t->state)
187    {
188    case RW_T2T_STATE_DETECT_TLV:
189        if (p_t2t->tlv_detect == TAG_NDEF_TLV)
190            rw_event = RW_T2T_NDEF_DETECT_EVT;
191        else
192            rw_event = RW_T2T_TLV_DETECT_EVT;
193
194        break;
195
196    case RW_T2T_STATE_READ_NDEF:
197        rw_event = RW_T2T_NDEF_READ_EVT;
198        break;
199
200    case RW_T2T_STATE_WRITE_NDEF:
201        rw_event = RW_T2T_NDEF_WRITE_EVT;
202        break;
203
204    case RW_T2T_STATE_SET_TAG_RO:
205        rw_event = RW_T2T_SET_TAG_RO_EVT;
206        break;
207
208    case RW_T2T_STATE_CHECK_PRESENCE:
209        rw_event = RW_T2T_PRESENCE_CHECK_EVT;
210        break;
211
212    case RW_T2T_STATE_FORMAT_TAG:
213        rw_event = RW_T2T_FORMAT_CPLT_EVT;
214        break;
215
216    default:
217	    rw_event = t2t_info_to_evt (p_info);
218        break;
219    }
220    return rw_event;
221}
222
223/*******************************************************************************
224**
225** Function         rw_t2t_handle_cc_read_rsp
226**
227** Description      Handle read cc bytes
228**
229** Returns          none
230**
231*******************************************************************************/
232static void rw_t2t_handle_cc_read_rsp (void)
233{
234    tRW_T2T_CB              *p_t2t  = &rw_cb.tcb.t2t;
235
236    if (  (  (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW)
237           &&(p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RO)  )
238                                    ||
239          (  (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO)
240           &&(p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO)
241           &&(p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO)  )  )
242    {
243        /* Invalid Version number or RWA byte */
244        rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_FAILED);
245        return;
246    }
247
248    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
249
250    if (rw_t2t_read ((UINT16) T2T_FIRST_DATA_BLOCK) != NFC_STATUS_OK)
251    {
252        rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_FAILED);
253    }
254}
255
256/*******************************************************************************
257**
258** Function         rw_t2t_ntf_tlv_detect_complete
259**
260** Description      Notify TLV detection complete to upper layer
261**
262** Returns          none
263**
264*******************************************************************************/
265static void rw_t2t_ntf_tlv_detect_complete (tNFC_STATUS status)
266{
267    tRW_T2T_CB              *p_t2t  = &rw_cb.tcb.t2t;
268    tRW_DETECT_NDEF_DATA    ndef_data = {0};
269    tRW_DETECT_TLV_DATA     tlv_data;
270    tRW_T2T_DETECT          evt_data;
271    UINT8                   xx;
272
273    if (p_t2t->tlv_detect == TAG_NDEF_TLV)
274    {
275        /* Notify upper layer the result of NDEF detect op */
276        ndef_data.status    = status;
277        ndef_data.protocol  = NFC_PROTOCOL_T2T;
278        ndef_data.flags     = rw_t2t_get_ndef_flags ();
279        ndef_data.cur_size  = p_t2t->ndef_msg_len;
280
281        if (status == NFC_STATUS_OK)
282            ndef_data.flags   |= RW_NDEF_FL_FORMATED;
283
284        if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] == T2T_CC3_RWA_RW)
285            ndef_data.max_size = (UINT32) rw_t2t_get_ndef_max_size ();
286        else
287            ndef_data.max_size = ndef_data.cur_size;
288
289        if (ndef_data.max_size < ndef_data.cur_size)
290        {
291            ndef_data.flags   |= RW_NDEF_FL_READ_ONLY;
292            ndef_data.max_size = ndef_data.cur_size;
293        }
294
295        if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY))
296        {
297            ndef_data.flags  |= RW_NDEF_FL_SOFT_LOCKABLE;
298            if (status == NFC_STATUS_OK)
299                ndef_data.flags |= RW_NDEF_FL_HARD_LOCKABLE;
300        }
301
302        rw_t2t_handle_op_complete ();
303        (*rw_cb.p_cback) (RW_T2T_NDEF_DETECT_EVT, (tRW_DATA *) &ndef_data);
304    }
305    else if (p_t2t->tlv_detect == TAG_PROPRIETARY_TLV)
306    {
307        evt_data.msg_len = p_t2t->prop_msg_len;
308        evt_data.status  = status;
309        rw_t2t_handle_op_complete ();
310        (*rw_cb.p_cback) (RW_T2T_TLV_DETECT_EVT, (tRW_DATA *) &evt_data);
311    }
312    else
313    {
314        /* Notify upper layer the result of Lock/Mem TLV detect op */
315        tlv_data.protocol   = NFC_PROTOCOL_T2T;
316        if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV)
317        {
318            tlv_data.num_bytes  = p_t2t->num_lockbytes;
319        }
320        else
321        {
322            tlv_data.num_bytes = 0;
323            for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
324            {
325                tlv_data.num_bytes += p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes;
326            }
327        }
328        tlv_data.status     = status;
329        rw_t2t_handle_op_complete ();
330        (*rw_cb.p_cback) (RW_T2T_TLV_DETECT_EVT, (tRW_DATA *) &tlv_data);
331    }
332
333}
334
335/*******************************************************************************
336**
337** Function         rw_t2t_handle_lock_read_rsp
338**
339** Description      Handle response to reading lock bytes
340**
341** Returns          none
342**
343*******************************************************************************/
344static void rw_t2t_handle_lock_read_rsp (UINT8 *p_data)
345{
346    UINT8                   updated_lock_byte;
347    UINT8                   num_locks;
348    UINT8                   offset = 0;
349    UINT16                  lock_offset;
350    UINT16                  base_lock_offset = 0;
351    tRW_T2T_CB              *p_t2t  = &rw_cb.tcb.t2t;
352    UINT16                  block;
353
354    /* Prepare NDEF/TLV attributes (based on current op) for sending response to upper layer */
355
356    num_locks = 0;
357    updated_lock_byte = 0;
358
359    /*  Extract all lock bytes present in the read 16 bytes
360     *  but atleast one lock byte (base lock) should be present in the read 16 bytes */
361
362    while (num_locks < p_t2t->num_lockbytes)
363    {
364        if (p_t2t->lockbyte[num_locks].b_lock_read == FALSE)
365        {
366            lock_offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset + p_t2t->lockbyte[num_locks].byte_index;
367            if (updated_lock_byte == 0)
368            {
369                /* The offset of the first lock byte present in the 16 bytes read using READ command */
370                base_lock_offset = lock_offset;
371                /* Block number used to read may not be the block where lock offset is present */
372                offset = (UINT8) (lock_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
373                /* Update the lock byte value in the control block */
374                p_t2t->lockbyte[num_locks].lock_byte = p_data[offset];
375                p_t2t->lockbyte[num_locks].b_lock_read = TRUE;
376                updated_lock_byte++;
377            }
378            else if (lock_offset > base_lock_offset)
379            {
380                /* Atleast one lock byte will get updated in the control block */
381                if ((lock_offset - base_lock_offset + offset) < T2T_READ_DATA_LEN)
382                {
383                    /* And this lock byte is also present in the read data */
384                    p_t2t->lockbyte[num_locks].lock_byte   = p_data[lock_offset - base_lock_offset + offset];
385                    p_t2t->lockbyte[num_locks].b_lock_read = TRUE;
386                    updated_lock_byte++;
387                }
388                else
389                {
390                    /* This lock byte is not present in the read data */
391                    block  = (UINT16) (lock_offset / T2T_BLOCK_LEN);
392                    block -= block % T2T_READ_BLOCKS;
393                    /* send READ command to read this lock byte */
394                    if (NFC_STATUS_OK != rw_t2t_read ((UINT16) block))
395                    {
396                        /* Unable to send Read command, notify failure status to upper layer */
397                        rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_FAILED);
398                    }
399                    break;
400                }
401            }
402            else
403            {
404                /* This Lock byte is not present in the read 16 bytes
405                 * send READ command to read the lock byte       */
406                if (NFC_STATUS_OK != rw_t2t_read ((UINT16) (lock_offset / T2T_BLOCK_LEN)))
407                {
408                    /* Unable to send Read command, notify failure status to upper layer */
409                    rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_FAILED);
410                }
411                break;
412            }
413        }
414        num_locks++;
415    }
416    if (num_locks == p_t2t->num_lockbytes)
417    {
418        /* All locks are read, notify upper layer */
419        rw_t2t_update_lock_attributes ();
420        rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_OK);
421    }
422}
423
424/*******************************************************************************
425**
426** Function         rw_t2t_handle_tlv_detect_rsp
427**
428** Description      Handle TLV detection.
429**
430** Returns          none
431**
432*******************************************************************************/
433static void rw_t2t_handle_tlv_detect_rsp (UINT8 *p_data)
434{
435    tRW_T2T_CB              *p_t2t = &rw_cb.tcb.t2t;
436    UINT16                  offset;
437    UINT16                  len = 0;
438    BOOLEAN                 failed = FALSE;
439    BOOLEAN                 found  = FALSE;
440    tRW_EVENT               event;
441    UINT8                   index;
442    UINT8                   count = 0;
443    UINT8                   xx;
444    tNFC_STATUS             status;
445    tT2T_CMD_RSP_INFO       *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info;
446    UINT8                   tlvtype = p_t2t->tlv_detect;
447
448    if (p_t2t->work_offset == 0)
449    {
450        /* Skip UID,Static Lock block,CC*/
451        p_t2t->work_offset = T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN;
452        p_t2t->b_read_data = TRUE;
453        memcpy (p_t2t->tag_data,  p_data, T2T_READ_DATA_LEN);
454    }
455
456    p_t2t->segment = 0;
457
458    for (offset = 0; offset < T2T_READ_DATA_LEN  && !failed && !found;)
459    {
460        if (rw_t2t_is_lock_res_byte ((UINT16) (p_t2t->work_offset + offset)) == TRUE)
461        {
462            /* Skip locks, reserved bytes while searching for TLV */
463            offset++;
464            continue;
465        }
466        switch (p_t2t->substate)
467        {
468        case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
469            /* Search for the tlv */
470            p_t2t->found_tlv = p_data[offset++];
471            switch (p_t2t->found_tlv)
472            {
473            case TAG_NULL_TLV:         /* May be used for padding. SHALL ignore this */
474                break;
475
476            case TAG_NDEF_TLV:
477                if (tlvtype == TAG_NDEF_TLV)
478                {
479                    /* NDEF Detected, now collect NDEF Attributes including NDEF Length */
480                    index = (offset % T2T_BLOCK_SIZE);
481                    /* Backup ndef first block */
482                    memcpy (p_t2t->ndef_first_block,&p_data[offset-index],index);
483                    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
484                }
485                else if (tlvtype == TAG_PROPRIETARY_TLV)
486                {
487                    /* Proprietary TLV can exist after NDEF Tlv so we continue searching */
488                    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
489                }
490                else if (  ((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0))
491                         ||((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))  )
492                {
493                    /* Lock / Memory control tlv cannot exist after NDEF TLV
494                     * So when NDEF is found, we stop searching for Lock and Memory control tlv */
495                    found = TRUE;
496                }
497                else
498                {
499                    /* While searching for Lock / Memory control tlv, if NDEF TLV is found
500                     * first then our search for Lock /Memory control tlv failed and we stop here */
501                    failed = TRUE;
502                }
503                break;
504
505            case TAG_LOCK_CTRL_TLV:
506            case TAG_MEM_CTRL_TLV:
507                p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
508                break;
509
510            case TAG_PROPRIETARY_TLV:
511                if (tlvtype == TAG_PROPRIETARY_TLV)
512                {
513                    index = (offset % T2T_BLOCK_SIZE);
514                    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
515                }
516                else
517                {
518                    /* NDEF/LOCK/MEM TLV can exist after Proprietary Tlv so we continue searching, skiping proprietary tlv */
519                    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
520                }
521                break;
522
523            case TAG_TERMINATOR_TLV:   /* Last TLV block in the data area. Must be no NDEF nessage */
524                if (  ((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0))
525                    ||((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))  )
526                {
527                    /* No more Lock/Memory TLV control tlv in the tag, so stop searching */
528                    found = TRUE;
529                }
530                else
531                {
532                    /* NDEF/Lock/Memory/Proprietary TLV cannot exist after Terminator Tlv */
533                    failed = TRUE;
534                }
535                break;
536            default:
537                failed = TRUE;
538            }
539            break;
540
541        case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
542            len = p_data[offset];
543            switch (p_t2t->found_tlv)
544            {
545            case TAG_NDEF_TLV:
546                p_t2t->ndef_header_offset = offset + p_t2t->work_offset;
547                if (len == TAG_LONG_NDEF_LEN_FIELD_BYTE0)
548                {
549                    /* The next two bytes constitute length bytes */
550                    p_t2t->substate     = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
551                }
552                else
553                {
554                    /* one byte length field */
555                    p_t2t->ndef_msg_len = len;
556                    p_t2t->bytes_count  = p_t2t->ndef_msg_len;
557                    p_t2t->substate     = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
558                }
559                break;
560
561            case TAG_PROPRIETARY_TLV:
562                if (len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
563                {
564                    /* The next two bytes constitute length bytes */
565                    p_t2t->substate     = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
566                }
567                else
568                {
569                    /* one byte length field */
570                    p_t2t->prop_msg_len = len;
571                    p_t2t->bytes_count  = p_t2t->prop_msg_len;
572                    p_t2t->substate     = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
573                }
574                break;
575            }
576            offset++;
577            break;
578
579        case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
580            switch (p_t2t->found_tlv)
581            {
582            case TAG_LOCK_CTRL_TLV:
583            case TAG_MEM_CTRL_TLV:
584
585                len = p_data[offset];
586                if (len == TAG_DEFAULT_TLV_LEN)
587                {
588                    /* Valid Lock control TLV */
589                    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
590                    p_t2t->bytes_count = TAG_DEFAULT_TLV_LEN;
591                }
592                else if (  ((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0))
593                         ||((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))  )
594                {
595                    /* Stop searching for Lock/ Memory control tlv */
596                    found = TRUE;
597                }
598                else
599                {
600                    failed = TRUE;
601                }
602                break;
603
604            case TAG_NDEF_TLV:
605            case TAG_PROPRIETARY_TLV:
606                /* The first length byte */
607                p_t2t->bytes_count  = (UINT8) p_data[offset];
608                p_t2t->substate     = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1;
609                break;
610            }
611            offset++;
612            break;
613
614        case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
615            /* Prepare NDEF Message length */
616            p_t2t->bytes_count  = (p_t2t->bytes_count << 8) + p_data[offset];
617            if (p_t2t->found_tlv == TAG_NDEF_TLV)
618            {
619                p_t2t->ndef_msg_len = p_t2t->bytes_count;
620            }
621            else if (p_t2t->found_tlv == TAG_PROPRIETARY_TLV)
622            {
623                p_t2t->prop_msg_len = p_t2t->bytes_count;
624            }
625            p_t2t->substate     = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
626            offset++;
627            break;
628
629        case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
630            switch (p_t2t->found_tlv)
631            {
632            case TAG_NDEF_TLV:
633                if (  (p_t2t->bytes_count == p_t2t->ndef_msg_len)
634                    &&(tlvtype == TAG_NDEF_TLV)  )
635                {
636                    /* The first byte offset after length field */
637                    p_t2t->ndef_msg_offset = offset + p_t2t->work_offset;
638                }
639                /* Reduce number of NDEF bytes remaining to pass over NDEF TLV */
640                if (p_t2t->bytes_count > 0)
641                    p_t2t->bytes_count--;
642
643                if (tlvtype == TAG_NDEF_TLV)
644                {
645                    found = TRUE;
646                    p_t2t->ndef_status = T2T_NDEF_DETECTED;
647                }
648                else if (p_t2t->bytes_count == 0)
649                {
650                    /* Next byte could be a different TLV */
651                    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
652                }
653                break;
654
655            case TAG_LOCK_CTRL_TLV:
656                p_t2t->bytes_count--;
657                if (  (tlvtype == TAG_LOCK_CTRL_TLV)
658                    ||(tlvtype == TAG_NDEF_TLV)  )
659                {
660                    /* Collect Lock TLV */
661                    p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
662                    if (p_t2t->bytes_count == 0)
663                    {
664                        /* Lock TLV is collected and buffered in tlv_value, now decode it */
665                        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset   = (p_t2t->tlv_value[0] >> 4) & 0x0F;
666                        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset  *= (UINT8) tags_pow (2, p_t2t->tlv_value[2] & 0x0F);
667                        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset  += p_t2t->tlv_value[0] & 0x0F;
668                        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit = (UINT8) tags_pow (2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
669                        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits = p_t2t->tlv_value[1];
670                        count = p_t2t->tlv_value[1] / 8 + ((p_t2t->tlv_value[1]%8 != 0)? 1:0);
671
672                        /* Extract lockbytes info addressed by this Lock TLV */
673                        xx = 0;
674                        while (xx < count)
675                        {
676                            p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index     = p_t2t->num_lock_tlvs;
677                            p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index    = xx;
678                            p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read   = FALSE;
679                            xx++;
680                            p_t2t->num_lockbytes++;
681                        }
682                        p_t2t->num_lock_tlvs++;
683                        rw_t2t_update_attributes ();
684                        /* Next byte could be a different TLV */
685                        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
686                    }
687                }
688                else
689                {
690                    /* If not looking for lock/ndef tlv, just skip this Lock TLV */
691                    if (p_t2t->bytes_count == 0)
692                    {
693                        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
694                    }
695                }
696                break;
697
698            case TAG_MEM_CTRL_TLV:
699                p_t2t->bytes_count--;
700                if (  (tlvtype == TAG_MEM_CTRL_TLV)
701                    ||(tlvtype == TAG_NDEF_TLV)  )
702                {
703                    p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
704                    if (p_t2t->bytes_count == 0)
705                    {
706                        if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS)
707                        {
708                            RW_TRACE_ERROR0 ("rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated for Memory tlv has reached");
709                            failed  = TRUE;
710                        }
711                        else
712                        {
713                            /* Extract memory control tlv */
714                            p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset    = (p_t2t->tlv_value[0] >> 4) & 0x0F;
715                            p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset   *= (UINT8) tags_pow (2, p_t2t->tlv_value[2] & 0x0F);
716                            p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset   += p_t2t->tlv_value[0] & 0x0F;
717                            p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes = p_t2t->tlv_value[1];
718                            p_t2t->num_mem_tlvs++;
719                            rw_t2t_update_attributes ();
720                            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
721                        }
722                    }
723                }
724                else
725                {
726                    if (p_t2t->bytes_count == 0)
727                    {
728                        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
729                    }
730                }
731                break;
732
733            case TAG_PROPRIETARY_TLV:
734                p_t2t->bytes_count--;
735                if (tlvtype == TAG_PROPRIETARY_TLV)
736                {
737                    found = TRUE;
738                    p_t2t->prop_msg_len = len;
739                }
740                else
741                {
742                    if (p_t2t->bytes_count == 0)
743                    {
744                        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
745                    }
746                }
747                break;
748            }
749            offset++;
750            break;
751        }
752    }
753
754
755    p_t2t->work_offset += T2T_READ_DATA_LEN;
756
757    event = rw_t2t_info_to_event (p_cmd_rsp_info);
758
759    /* If not found and not failed, read next block and search tlv */
760    if (!found && !failed)
761    {
762
763        if (p_t2t->work_offset >= (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR))
764        {
765            if (  ((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0))
766                ||((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))  )
767            {
768                found = TRUE;
769            }
770            else
771            {
772                failed = TRUE;
773            }
774        }
775        else
776        {
777            if (rw_t2t_read ((UINT16) ((p_t2t->work_offset / T2T_BLOCK_LEN) + T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
778                failed = TRUE;
779        }
780    }
781
782    if (failed || found)
783    {
784        if (tlvtype == TAG_LOCK_CTRL_TLV)
785        {
786            /* Incase no Lock control tlv is present then look for default dynamic lock bytes */
787            rw_t2t_extract_default_locks_info ();
788
789            /* Send command to read the dynamic lock bytes */
790            status = rw_t2t_read_locks ();
791
792            if (status != NFC_STATUS_CONTINUE)
793            {
794                /* If unable to read a lock/all locks read, notify upper layer */
795                rw_t2t_update_lock_attributes ();
796                rw_t2t_ntf_tlv_detect_complete (status);
797            }
798        }
799        else if (tlvtype == TAG_NDEF_TLV)
800        {
801            rw_t2t_extract_default_locks_info ();
802
803            if (failed)
804            {
805                rw_t2t_ntf_tlv_detect_complete (NFC_STATUS_FAILED);
806            }
807            else
808            {
809                /* NDEF present,Send command to read the dynamic lock bytes */
810                status = rw_t2t_read_locks ();
811                if (status != NFC_STATUS_CONTINUE)
812                {
813                    /* If unable to read a lock/all locks read, notify upper layer */
814                    rw_t2t_update_lock_attributes ();
815                    rw_t2t_ntf_tlv_detect_complete (status);
816                }
817            }
818        }
819        else
820        {
821            /* Notify Memory/ Proprietary tlv detect result */
822            status  = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
823            rw_t2t_ntf_tlv_detect_complete (status);
824        }
825    }
826}
827
828/*******************************************************************************
829**
830** Function         rw_t2t_read_locks
831**
832** Description      This function will send command to read next unread locks
833**
834** Returns          NFC_STATUS_OK, if all locks are read successfully
835**                  NFC_STATUS_FAILED, if reading locks failed
836**                  NFC_STATUS_CONTINUE, if reading locks is in progress
837**
838*******************************************************************************/
839tNFC_STATUS rw_t2t_read_locks (void)
840{
841    UINT8       num_locks   = 0;
842    tRW_T2T_CB  *p_t2t      = &rw_cb.tcb.t2t;
843    tNFC_STATUS status      = NFC_STATUS_CONTINUE;
844    UINT16      offset;
845    UINT16      block;
846
847    if (  (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW)
848        ||((p_t2t->tag_hdr[0] == TAG_MIFARE_MID) && (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_MULC))
849        ||((p_t2t->tag_hdr[0] == TAG_MIFARE_MID) && (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_MUL))  )
850
851    {
852        /* Skip reading dynamic lock bytes if CC is set as Read only or on MUL/MUL-C tag */
853        while (num_locks < p_t2t->num_lockbytes)
854        {
855            p_t2t->lockbyte[num_locks].lock_byte   = 0x00;
856            p_t2t->lockbyte[num_locks].b_lock_read = TRUE;
857            num_locks++;
858        }
859    }
860
861    while (num_locks < p_t2t->num_lockbytes)
862    {
863        if (p_t2t->lockbyte[num_locks].b_lock_read == FALSE)
864        {
865            /* Send Read command to read the first un read locks */
866            offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset + p_t2t->lockbyte[num_locks].byte_index;
867
868            /* Read 16 bytes where this lock byte is present */
869            block  = (UINT16) (offset / T2T_BLOCK_LEN);
870            block -= block % T2T_READ_BLOCKS;
871
872            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
873            /* send READ8 command */
874            if ((status = rw_t2t_read ((UINT16) block)) == NFC_STATUS_OK)
875            {
876                /* Reading Locks */
877                status          = NFC_STATUS_CONTINUE;
878            }
879            else
880            {
881                status = NFC_STATUS_FAILED;
882            }
883            break;
884        }
885        num_locks++;
886    }
887    if (num_locks == p_t2t->num_lockbytes)
888    {
889        /* All locks are read */
890        status = NFC_STATUS_OK;
891    }
892
893    return status;
894}
895
896/*******************************************************************************
897**
898** Function         rw_t2t_extract_default_locks_info
899**
900** Description      This function will prepare lockbytes information for default
901**                  locks present in the tag in the absence of lock control tlv.
902**                  Adding a virtual lock control tlv for these lock bytes for
903**                  easier manipulation.
904**
905** Returns          None
906**
907*******************************************************************************/
908void rw_t2t_extract_default_locks_info (void)
909{
910    UINT8       num_dynamic_lock_bits;
911    UINT8       num_dynamic_lock_bytes;
912    UINT8       xx;
913    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
914    const       tT2T_INIT_TAG *p_ret;
915    UINT8       bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
916
917
918    if (  (p_t2t->num_lock_tlvs == 0)
919        &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)  )
920    {
921        /* No Lock control tlv is detected. Indicates lock bytes are present in default location */
922        /* Add a virtual Lock tlv to map this default lock location */
923        if ((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], FALSE, 0)) != NULL)
924            bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
925
926        num_dynamic_lock_bits   = ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) - (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) / bytes_locked_per_lock_bit;
927        num_dynamic_lock_bytes  = num_dynamic_lock_bits / 8;
928        num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0:1;
929
930        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset                = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) + (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
931        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit  = bytes_locked_per_lock_bit;
932        p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits              = num_dynamic_lock_bits;
933
934        /* Based on tag data size the number of locks present in the default location changes */
935        for (xx = 0; xx < num_dynamic_lock_bytes; xx++)
936        {
937            p_t2t->lockbyte[xx].tlv_index   = p_t2t->num_lock_tlvs;
938            p_t2t->lockbyte[xx].byte_index  = xx;
939            p_t2t->lockbyte[xx].b_lock_read = FALSE;
940        }
941        p_t2t->num_lockbytes = num_dynamic_lock_bytes;
942        p_t2t->num_lock_tlvs = 1;
943    }
944}
945
946/*******************************************************************************
947**
948** Function         rw_t2t_read_ndef_last_block
949**
950** Description      This function will locate and read the last ndef block.
951**                  The last ndef block refers to the tag block where last byte
952**                  of new ndef message will reside. Also this function will
953**                  locate the offset of Terminator TLV based on the size of
954**                  new NDEF Message
955**
956** Returns          NCI_STATUS_OK,if able to locate last ndef block & read started
957**                  Otherwise, error status.
958**
959*******************************************************************************/
960tNFC_STATUS rw_t2t_read_ndef_last_block (void)
961{
962    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
963    UINT16      header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN) ? T2T_LONG_NDEF_LEN_FIELD_LEN : T2T_SHORT_NDEF_LEN_FIELD_LEN;
964    UINT16      num_ndef_bytes;
965    UINT16      total_ndef_bytes;
966    UINT16      last_ndef_byte_offset;
967    UINT16      terminator_tlv_byte_index;
968    tNFC_STATUS status;
969    UINT16      block;
970
971
972    total_ndef_bytes        = header_len + p_t2t->new_ndef_msg_len;
973    num_ndef_bytes          = 0;
974    last_ndef_byte_offset   = p_t2t->ndef_header_offset;
975
976    /* Locate NDEF final block based on the size of new NDEF Message */
977    while (num_ndef_bytes < total_ndef_bytes)
978    {
979        if (rw_t2t_is_lock_res_byte ((UINT16) (last_ndef_byte_offset)) == FALSE)
980            num_ndef_bytes++;
981
982        last_ndef_byte_offset++;
983    }
984    p_t2t->ndef_last_block_num = (UINT16) ((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
985    block  = p_t2t->ndef_last_block_num;
986
987    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
988    /* Read NDEF last block before updating */
989    if ((status = rw_t2t_read (block))== NFC_STATUS_OK)
990    {
991        if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len)
992        {
993            /* Locate Terminator TLV Block */
994            total_ndef_bytes++;
995            terminator_tlv_byte_index = last_ndef_byte_offset;
996
997            while (num_ndef_bytes < total_ndef_bytes)
998            {
999                if (rw_t2t_is_lock_res_byte ((UINT16) terminator_tlv_byte_index) == FALSE)
1000                        num_ndef_bytes++;
1001
1002                terminator_tlv_byte_index++;
1003            }
1004
1005            p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
1006        }
1007        else
1008        {
1009            /* No space for Terminator TLV */
1010            p_t2t->terminator_byte_index = 0x00;
1011        }
1012    }
1013    return status;
1014}
1015
1016/*******************************************************************************
1017**
1018** Function         rw_t2t_read_terminator_tlv_block
1019**
1020** Description      This function will read the block where terminator tlv will
1021**                  be added later
1022**
1023** Returns          NCI_STATUS_OK, if read was started. Otherwise, error status.
1024**
1025*******************************************************************************/
1026tNFC_STATUS rw_t2t_read_terminator_tlv_block (void)
1027{
1028    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1029    tNFC_STATUS status;
1030    UINT16      block;
1031
1032    /* Send read command to read base block (Block % 4==0) where this block is also read as part of 16 bytes */
1033    block  = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
1034    block -= block % T2T_READ_BLOCKS;
1035
1036    p_t2t->substate         = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
1037    /* Read the block where Terminator TLV may be added later during NDEF Write operation */
1038    status = rw_t2t_read (block);
1039    return status;
1040}
1041
1042/*******************************************************************************
1043**
1044** Function         rw_t2t_read_ndef_next_block
1045**
1046** Description      This function will read the tag block passed as argument
1047**
1048** Returns          NCI_STATUS_OK, if read was started. Otherwise, error status.
1049**
1050*******************************************************************************/
1051tNFC_STATUS rw_t2t_read_ndef_next_block (UINT16 block)
1052{
1053    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1054    tNFC_STATUS status;
1055
1056    /* Send read command to read base block (Block % 4==0) where this block is also read as part of 16 bytes */
1057    block -= block % T2T_READ_BLOCKS;
1058
1059    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
1060    /* Read the block */
1061    status = rw_t2t_read (block);
1062
1063    return status;
1064}
1065
1066/*******************************************************************************
1067**
1068** Function         rw_t2t_is_read_before_write_block
1069**
1070** Description      This function will check if the block has to be read before
1071**                  writting to avoid over writting in to lock/reserved bytes
1072**                  present in the block.
1073**                  If no bytes in the block can be overwritten it moves in to
1074**                  next block and check. Finally it finds a block where part of
1075**                  ndef bytes can exist and check if the whole block can be
1076**                  updated or only part of block can be modified.
1077**
1078** Returns          TRUE, if the block returned should be read before writting
1079**                  FALSE, if the block need not be read as it was already
1080**                         read or during NDEF write we may completely overwrite
1081**                         the block and there is no reserved or locked bytes in
1082**                         that block
1083**
1084*******************************************************************************/
1085static BOOLEAN rw_t2t_is_read_before_write_block (UINT16 block, UINT16 *p_block_to_read)
1086{
1087    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
1088    UINT8       *p_cc   = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1089    UINT8       count;
1090    UINT8       index;
1091    UINT16      tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1092    BOOLEAN     read_before_write = TRUE;
1093
1094
1095    if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE)
1096    {
1097        /* First NDEF block is already read */
1098        read_before_write = FALSE;
1099        memcpy (p_t2t->ndef_read_block,p_t2t->ndef_first_block,T2T_BLOCK_SIZE);
1100    }
1101    else if (block == p_t2t->ndef_last_block_num)
1102    {
1103        /* Last NDEF block is already read */
1104        read_before_write = FALSE;
1105        memcpy (p_t2t->ndef_read_block,p_t2t->ndef_last_block,T2T_BLOCK_SIZE);
1106    }
1107    else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE)
1108    {
1109        /* Terminator tlv block is already read */
1110        read_before_write = FALSE;
1111        memcpy (p_t2t->ndef_read_block,p_t2t->terminator_tlv_block,T2T_BLOCK_SIZE);
1112    }
1113    else
1114    {
1115        count = 0;
1116        while (block < tag_size)
1117        {
1118            index = 0;
1119
1120            while (index < T2T_BLOCK_SIZE)
1121            {
1122                /* check if it is a reserved or locked byte */
1123                if (rw_t2t_is_lock_res_byte ((UINT16) ((block * T2T_BLOCK_SIZE) + index)) == FALSE)
1124                {
1125                    count++;
1126                }
1127                index++;
1128            }
1129            if (count == T2T_BLOCK_SIZE)
1130            {
1131                /* All the bytes in the block are free to NDEF write  */
1132                read_before_write = FALSE;
1133                break;
1134            }
1135            else if (count == 0)
1136            {
1137                /* The complete block is not free for NDEF write  */
1138                index = 0;
1139                block++;
1140            }
1141            else
1142            {
1143                /* The block has reseved byte (s) or locked byte (s) or both */
1144                read_before_write = TRUE;
1145                break;
1146            }
1147        }
1148    }
1149    /* Return the block to read next before NDEF write */
1150    *p_block_to_read = block;
1151    return read_before_write;
1152}
1153
1154/*******************************************************************************
1155**
1156** Function         rw_t2t_write_ndef_first_block
1157**
1158** Description      This function will write the first NDEF block with Length
1159**                  field reset to zero.
1160**                  Also after writting NDEF this function may be called to
1161**                  update new NDEF length
1162**
1163** Returns          NCI_STATUS_OK, if write was started. Otherwise, error status.
1164**
1165*******************************************************************************/
1166tNFC_STATUS rw_t2t_write_ndef_first_block (UINT16 msg_len, BOOLEAN b_update_len)
1167{
1168    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1169    UINT8       new_lengthfield_len;
1170    UINT8       write_block[4];
1171    UINT8       block;
1172    UINT8       *p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1173    UINT16      total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1174    tNFC_STATUS status;
1175    UINT8       length_field[3];
1176    UINT8       index;
1177
1178    p_t2t->work_offset = 0;
1179    new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN ? T2T_LONG_NDEF_LEN_FIELD_LEN : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1180    if (new_lengthfield_len == 3)
1181    {
1182        /* New NDEF is Long NDEF */
1183        if (msg_len == 0)
1184        {
1185            /* Clear NDEF length field */
1186            length_field[0] = 0x00;
1187            length_field[1] = 0x00;
1188            length_field[2] = 0x00;
1189        }
1190        else
1191        {
1192            /* Update NDEF length field with new NDEF Msg len */
1193            length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1194            length_field[1] = (UINT8) (msg_len >> 8);
1195            length_field[2] = (UINT8) (msg_len);
1196        }
1197    }
1198    else
1199    {
1200        /* New NDEF is Short NDEF */
1201        length_field[0] = (UINT8) (msg_len);
1202    }
1203
1204    /* updating ndef_first_block with new ndef message */
1205    memcpy (write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
1206
1207    index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1208    block = (UINT8) (p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
1209
1210    while (p_t2t->work_offset == 0 && block < total_blocks)
1211    {
1212        /* update length field */
1213        while (index < T2T_BLOCK_SIZE && p_t2t->work_offset < p_t2t->new_ndef_msg_len)
1214        {
1215            if (rw_t2t_is_lock_res_byte ((UINT16) ((block * T2T_BLOCK_SIZE) + index)) == FALSE)
1216            {
1217                write_block[index] = length_field[p_t2t->work_offset];
1218                p_t2t->work_offset++;
1219            }
1220            index++;
1221            if (p_t2t->work_offset == new_lengthfield_len)
1222            {
1223                break;
1224            }
1225        }
1226        /* If more space in this block then add ndef message */
1227        while (index < T2T_BLOCK_SIZE && p_t2t->work_offset < (p_t2t->new_ndef_msg_len + new_lengthfield_len))
1228        {
1229            if (rw_t2t_is_lock_res_byte ((UINT16) ((block * T2T_BLOCK_SIZE) + index)) == FALSE)
1230            {
1231                write_block[index] = p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1232                p_t2t->work_offset++;
1233            }
1234            index++;
1235        }
1236        if (p_t2t->work_offset == 0)
1237        {
1238            /* If no bytes are written move to next block */
1239            index = 0;
1240            block++;
1241            if (block == p_t2t->ndef_last_block_num)
1242            {
1243                memcpy (write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1244            }
1245        }
1246    }
1247    if (p_t2t->work_offset == 0)
1248    {
1249        status  = NFC_STATUS_FAILED;
1250    }
1251    else
1252    {
1253        rw_t2t_update_cb (block, write_block, b_update_len);
1254        /* Update the identified block with newly prepared data */
1255        if ((status = rw_t2t_write (block, write_block)) == NFC_STATUS_OK)
1256        {
1257            p_t2t->b_read_data = FALSE;
1258        }
1259    }
1260    return status;
1261}
1262
1263/*******************************************************************************
1264**
1265** Function         rw_t2t_write_ndef_next_block
1266**
1267** Description      This function can be called to write an NDEF message block
1268**
1269** Returns          NCI_STATUS_OK, if write was started. Otherwise, error status.
1270**
1271*******************************************************************************/
1272tNFC_STATUS rw_t2t_write_ndef_next_block (UINT16 block, UINT16 msg_len, BOOLEAN b_update_len)
1273{
1274    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1275    UINT8       new_lengthfield_len;
1276    UINT8       write_block[4];
1277    UINT8       *p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1278    UINT16      total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1279    UINT16      initial_offset;
1280    UINT8       length_field[3];
1281    UINT8       index;
1282    tNFC_STATUS status;
1283
1284    /* Write NDEF Message */
1285    new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN ? T2T_LONG_NDEF_LEN_FIELD_LEN : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1286
1287    index = 0;
1288
1289    memcpy (write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
1290
1291    if (p_t2t->work_offset >= new_lengthfield_len)
1292    {
1293        /* Length field is updated, write ndef message field */
1294        initial_offset = p_t2t->work_offset;
1295        while (p_t2t->work_offset == initial_offset && block < total_blocks)
1296        {
1297            while (index < T2T_BLOCK_SIZE && p_t2t->work_offset < (p_t2t->new_ndef_msg_len + new_lengthfield_len))
1298            {
1299                if (rw_t2t_is_lock_res_byte ((UINT16) ((block * T2T_BLOCK_SIZE) + index)) == FALSE)
1300                {
1301                    write_block[index] = p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1302                    p_t2t->work_offset++;
1303                }
1304                index++;
1305            }
1306            if (p_t2t->work_offset == initial_offset)
1307            {
1308                index = 0;
1309                block++;
1310            }
1311        }
1312    }
1313    else
1314    {
1315        /* Complete writting Length field and then write ndef message */
1316        new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN ? T2T_LONG_NDEF_LEN_FIELD_LEN : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1317        if (new_lengthfield_len == 3)
1318        {
1319            /* New NDEF is Long NDEF */
1320            if (msg_len == 0)
1321            {
1322                length_field[0] = 0x00;
1323                length_field[1] = 0x00;
1324                length_field[2] = 0x00;
1325            }
1326            else
1327            {
1328                length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1329                length_field[1] = (UINT8) (msg_len >> 8);
1330                length_field[2] = (UINT8) (msg_len);
1331            }
1332        }
1333        else
1334        {
1335            /* New NDEF is short NDEF */
1336            length_field[0] = (UINT8) (msg_len);
1337        }
1338        initial_offset = p_t2t->work_offset;
1339        while (p_t2t->work_offset == initial_offset && block < total_blocks)
1340        {
1341            /* Update length field */
1342            while (index < T2T_BLOCK_SIZE && p_t2t->work_offset < p_t2t->new_ndef_msg_len)
1343            {
1344                if (rw_t2t_is_lock_res_byte ((UINT16) ((block * T2T_BLOCK_SIZE) + index)) == FALSE)
1345                {
1346                    write_block[index] = length_field[p_t2t->work_offset];
1347                    p_t2t->work_offset++;
1348                }
1349                index++;
1350                if (p_t2t->work_offset == new_lengthfield_len)
1351                {
1352                    break;
1353                }
1354            }
1355            /* Update ndef message field */
1356            while (index < T2T_BLOCK_SIZE && p_t2t->work_offset < (p_t2t->new_ndef_msg_len + new_lengthfield_len))
1357            {
1358                if (rw_t2t_is_lock_res_byte ((UINT16) ((block * T2T_BLOCK_SIZE) + index)) == FALSE)
1359                {
1360                    write_block[index] = p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1361                    p_t2t->work_offset++;
1362                }
1363                index++;
1364            }
1365            if (p_t2t->work_offset == initial_offset)
1366            {
1367                index = 0;
1368                block++;
1369            }
1370        }
1371    }
1372    if (p_t2t->work_offset == initial_offset)
1373    {
1374        status  = NFC_STATUS_FAILED;
1375    }
1376    else
1377    {
1378        rw_t2t_update_cb (block, write_block, b_update_len);
1379        /* Write the NDEF Block */
1380        status = rw_t2t_write (block, write_block);
1381    }
1382
1383    return status;
1384}
1385
1386/*******************************************************************************
1387**
1388** Function         rw_t2t_update_cb
1389**
1390** Description      This function can be called to write an NDEF message block
1391**
1392** Returns          NCI_STATUS_OK, if write was started. Otherwise, error status.
1393**
1394*******************************************************************************/
1395static void rw_t2t_update_cb (UINT16 block, UINT8 *p_write_block, BOOLEAN b_update_len)
1396{
1397    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1398    UINT8       new_lengthfield_len;
1399
1400        /* Write NDEF Message */
1401    new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN ? T2T_LONG_NDEF_LEN_FIELD_LEN : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1402
1403    if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE)
1404    {
1405        /* Update ndef first block if the 'block' points to ndef first block */
1406        memcpy (p_t2t->ndef_first_block,p_write_block,T2T_BLOCK_SIZE);
1407    }
1408    if (p_t2t->terminator_byte_index/T2T_BLOCK_SIZE == block)
1409    {
1410        /* Update terminator block if the 'block' points to terminator tlv block */
1411        memcpy (p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1412    }
1413    if (b_update_len == FALSE)
1414    {
1415        if (block == p_t2t->ndef_last_block_num)
1416        {
1417            p_t2t->substate         = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1418            p_t2t->work_offset      = 0;
1419            /* Update ndef final block if the 'block' points to ndef final block */
1420            memcpy (p_t2t->ndef_last_block,p_write_block,T2T_BLOCK_SIZE);
1421        }
1422        else
1423        {
1424            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
1425        }
1426    }
1427    else
1428    {
1429        if (block == p_t2t->ndef_last_block_num)
1430        {
1431            /* Update the backup of Ndef final block TLV block */
1432            memcpy (p_t2t->ndef_last_block,p_write_block,T2T_BLOCK_SIZE);
1433        }
1434
1435        if (p_t2t->work_offset >= new_lengthfield_len)
1436        {
1437            if (p_t2t->terminator_byte_index != 0)
1438            {
1439                /* Add Terminator TLV as part of NDEF Write operation */
1440                p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1441            }
1442            else
1443            {
1444                /* Skip adding Terminator TLV */
1445                p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1446            }
1447        }
1448        else
1449        {
1450            /* Part of NDEF Message Len should be added in the next block */
1451            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
1452        }
1453    }
1454}
1455
1456/*******************************************************************************
1457**
1458** Function         rw_t2t_get_ndef_flags
1459**
1460** Description      Prepare NDEF Flags
1461**
1462** Returns          NDEF Flag value
1463**
1464*******************************************************************************/
1465static UINT8 rw_t2t_get_ndef_flags (void)
1466{
1467    UINT8       flags   = 0;
1468    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
1469    const       tT2T_INIT_TAG *p_ret;
1470
1471    flags |= RW_NDEF_FL_SUPPORTED;
1472
1473    if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) || (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1474        flags |= RW_NDEF_FL_FORMATABLE;
1475
1476    if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1477        flags |=RW_NDEF_FL_READ_ONLY;
1478
1479    if (  ((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], FALSE, 0)) != NULL)
1480        &&(p_ret->b_otp)  )
1481    {
1482        /* Set otp flag */
1483        flags |= RW_NDEF_FL_OTP;
1484
1485        /* Set Read only flag if otp tag already has NDEF Message */
1486        if (p_t2t->ndef_msg_len)
1487            flags |= RW_NDEF_FL_READ_ONLY;
1488    }
1489    return flags;
1490}
1491
1492/*******************************************************************************
1493**
1494** Function         rw_t2t_get_ndef_max_size
1495**
1496** Description      Calculate maximum size of NDEF message that can be written
1497**                  on to the tag
1498**
1499** Returns          Maximum size of NDEF Message
1500**
1501*******************************************************************************/
1502static UINT16 rw_t2t_get_ndef_max_size (void)
1503{
1504    UINT16      offset;
1505    UINT8       xx;
1506    tRW_T2T_CB  *p_t2t   = &rw_cb.tcb.t2t;
1507    UINT16      tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) + (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) + p_t2t->num_lockbytes;
1508
1509    for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1510        tag_size += p_t2t->mem_tlv[xx].num_bytes;
1511
1512    offset                  = p_t2t->ndef_msg_offset;
1513    p_t2t->max_ndef_msg_len = 0;
1514
1515    if (  (tag_size < T2T_STATIC_SIZE)
1516        ||(tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR))
1517        ||((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) && (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))  )
1518    {
1519        /* Tag not formated, assume static tag */
1520        p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE - T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
1521        return p_t2t->max_ndef_msg_len;
1522    }
1523
1524    /* Starting from NDEF Message offset find the first locked data byte */
1525    while (offset < tag_size)
1526    {
1527        if (rw_t2t_is_lock_res_byte ((UINT16) offset) == FALSE)
1528        {
1529            if (rw_t2t_is_read_only_byte ((UINT16) offset) == TRUE)
1530                break;
1531            p_t2t->max_ndef_msg_len++;
1532        }
1533        offset++;
1534    }
1535    /* NDEF Length field length changes based on NDEF size */
1536    if (  (p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1537        &&((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) == T2T_SHORT_NDEF_LEN_FIELD_LEN)  )
1538    {
1539        p_t2t->max_ndef_msg_len -=  (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0) ? 1: (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1540    }
1541    return p_t2t->max_ndef_msg_len;
1542}
1543
1544/*******************************************************************************
1545**
1546** Function         rw_t2t_add_terminator_tlv
1547**
1548** Description      This function will add terminator TLV after NDEF Message
1549**
1550** Returns          NCI_STATUS_OK, if write was started. Otherwise, error status.
1551**
1552*******************************************************************************/
1553tNFC_STATUS rw_t2t_add_terminator_tlv (void)
1554{
1555    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1556    tNFC_STATUS status;
1557    UINT16      block;
1558
1559    /* Add Terminator TLV after NDEF Message */
1560    p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index%T2T_BLOCK_LEN] = TAG_TERMINATOR_TLV;
1561    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1562
1563    block = p_t2t->terminator_byte_index/T2T_BLOCK_LEN;
1564    status = rw_t2t_write (block, p_t2t->terminator_tlv_block);
1565
1566    return status;
1567}
1568
1569/*******************************************************************************
1570**
1571** Function         rw_t2t_handle_ndef_read_rsp
1572**
1573** Description      This function handles reading an NDEF message.
1574**
1575** Returns          none
1576**
1577*******************************************************************************/
1578static void rw_t2t_handle_ndef_read_rsp (UINT8 *p_data)
1579{
1580    tRW_T2T_CB      *p_t2t = &rw_cb.tcb.t2t;
1581    tRW_READ_DATA    evt_data;
1582    UINT16          len;
1583    UINT16          offset;
1584    BOOLEAN         failed = FALSE;
1585    BOOLEAN         done   = FALSE;
1586
1587    /* On the first read, adjust for any partial block offset */
1588    offset = 0;
1589    len    = T2T_READ_DATA_LEN;
1590
1591    if (p_t2t->work_offset == 0)
1592    {
1593        /* The Ndef Message offset may be present in the read 16 bytes */
1594        offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1595    }
1596
1597    /* Skip all reserved and lock bytes */
1598    while (  (offset < len)
1599           &&(p_t2t->work_offset<p_t2t->ndef_msg_len)  )
1600
1601    {
1602        if (rw_t2t_is_lock_res_byte ((UINT16) (offset + p_t2t->block_read * T2T_BLOCK_LEN)) == FALSE)
1603        {
1604            /* Collect the NDEF Message */
1605            p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1606            p_t2t->work_offset++;
1607        }
1608        offset++;
1609    }
1610
1611    if (p_t2t->work_offset >= p_t2t->ndef_msg_len)
1612    {
1613        done = TRUE;
1614        p_t2t->ndef_status = T2T_NDEF_READ;
1615    }
1616    else
1617    {
1618        /* Read next 4 blocks */
1619        if (rw_t2t_read ((UINT16) (p_t2t->block_read + T2T_READ_BLOCKS)) != NFC_STATUS_OK)
1620            failed = TRUE;
1621    }
1622
1623    if (failed || done)
1624    {
1625        evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1626        evt_data.p_data = NULL;
1627        rw_t2t_handle_op_complete ();
1628        (*rw_cb.p_cback) (RW_T2T_NDEF_READ_EVT, (tRW_DATA *) &evt_data);
1629    }
1630}
1631
1632/*******************************************************************************
1633**
1634** Function         rw_t2t_handle_ndef_write_rsp
1635**
1636** Description      Handle response received to reading (or part of) NDEF message.
1637**
1638** Returns          none
1639**
1640*******************************************************************************/
1641static void rw_t2t_handle_ndef_write_rsp (UINT8 *p_data)
1642{
1643    tRW_T2T_CB      *p_t2t = &rw_cb.tcb.t2t;
1644    tRW_READ_DATA   evt_data;
1645    BOOLEAN         failed = FALSE;
1646    BOOLEAN         done   = FALSE;
1647    UINT16          block;
1648    UINT8           offset;
1649
1650    switch (p_t2t->substate)
1651    {
1652    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1653
1654        /* Backup the read NDEF first block */
1655           memcpy (p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1656        /* Read ndef final block */
1657        if (rw_t2t_read_ndef_last_block () !=  NFC_STATUS_OK)
1658            failed = TRUE;
1659        break;
1660
1661    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1662
1663        offset = (UINT8) (p_t2t->ndef_last_block_num - p_t2t->block_read) * T2T_BLOCK_SIZE;
1664        /* Backup the read NDEF final block */
1665        memcpy (p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1666        if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) == p_t2t->ndef_last_block_num)
1667        {
1668            /* If Terminator TLV will reside on the NDEF Final block */
1669            memcpy (p_t2t->terminator_tlv_block, p_t2t->ndef_last_block, T2T_BLOCK_LEN);
1670            if (rw_t2t_write_ndef_first_block (0x0000, FALSE)!=  NFC_STATUS_OK)
1671                failed = TRUE;
1672        }
1673        else if (p_t2t->terminator_byte_index != 0)
1674        {
1675            /* If there is space for Terminator TLV and if it will reside outside NDEF Final block */
1676            if (rw_t2t_read_terminator_tlv_block ()!=  NFC_STATUS_OK)
1677                failed = TRUE;
1678        }
1679        else
1680        {
1681            if (rw_t2t_write_ndef_first_block (0x0000, FALSE)!=  NFC_STATUS_OK)
1682                failed = TRUE;
1683        }
1684        break;
1685
1686    case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1687
1688        offset = (UINT8) (((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) - p_t2t->block_read) * T2T_BLOCK_SIZE);
1689        /* Backup the read Terminator TLV block */
1690        memcpy (p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
1691
1692        /* Write the first block for new NDEF Message */
1693        if (rw_t2t_write_ndef_first_block (0x0000, FALSE)!=  NFC_STATUS_OK)
1694           failed = TRUE;
1695        break;
1696
1697    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1698
1699        offset = (UINT8) (p_t2t->ndef_read_block_num - p_t2t->block_read) * T2T_BLOCK_SIZE;
1700        /* Backup read block */
1701        memcpy (p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
1702
1703        /* Update the block with new NDEF Message */
1704        if (rw_t2t_write_ndef_next_block (p_t2t->ndef_read_block_num, 0x0000, FALSE) !=  NFC_STATUS_OK)
1705            failed = TRUE;
1706        break;
1707
1708    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1709    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
1710        if (rw_t2t_is_read_before_write_block ((UINT16) (p_t2t->block_written + 1), &block) == TRUE)
1711        {
1712            p_t2t->ndef_read_block_num = block;
1713            /* If only part of the block is going to be updated read the block to retain previous data for
1714               unchanged part of the block */
1715            if (rw_t2t_read_ndef_next_block (block) !=  NFC_STATUS_OK)
1716                failed = TRUE;
1717        }
1718        else
1719        {
1720            if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK)
1721            {
1722                /* Directly write the block with new NDEF contents as whole block is going to be updated */
1723                if (rw_t2t_write_ndef_next_block (block, p_t2t->new_ndef_msg_len, TRUE)!=  NFC_STATUS_OK)
1724                   failed = TRUE;
1725            }
1726            else
1727            {
1728                /* Directly write the block with new NDEF contents as whole block is going to be updated */
1729                if (rw_t2t_write_ndef_next_block (block, 0x0000, FALSE)!=  NFC_STATUS_OK)
1730                   failed = TRUE;
1731            }
1732        }
1733        break;
1734
1735    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
1736        /* Write the next block for new NDEF Message */
1737        p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1738        if (rw_t2t_is_read_before_write_block ((UINT16) (p_t2t->ndef_write_block), &block) == TRUE)
1739        {
1740            /* If only part of the block is going to be updated read the block to retain previous data for
1741               part of the block thats not going to be changed */
1742            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1743            if (rw_t2t_read (block) !=  NFC_STATUS_OK)
1744                failed = TRUE;
1745
1746        }
1747        else
1748        {
1749            /* Update NDEF Message Length in the Tag */
1750            if (rw_t2t_write_ndef_first_block (p_t2t->new_ndef_msg_len, TRUE)!=  NFC_STATUS_OK)
1751               failed = TRUE;
1752        }
1753        break;
1754
1755    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
1756        /* Backup read block */
1757        memcpy (p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
1758
1759        /* Update the block with new NDEF Message */
1760        if (rw_t2t_write_ndef_next_block (p_t2t->block_read, p_t2t->new_ndef_msg_len, TRUE) ==  NFC_STATUS_OK)
1761            p_t2t->ndef_write_block = p_t2t->block_read + 1;
1762        else
1763            failed = TRUE;
1764
1765        break;
1766
1767    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
1768        if (rw_t2t_add_terminator_tlv ()!=  NFC_STATUS_OK)
1769           failed = TRUE;
1770        break;
1771
1772    case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
1773        done = TRUE;
1774        break;
1775
1776    default:
1777        break;
1778    }
1779
1780    if (failed || done)
1781    {
1782        evt_data.p_data = NULL;
1783        /* NDEF WRITE Operation is done, inform up the stack */
1784        evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1785        if (done)
1786        {
1787            if (  (p_t2t->ndef_msg_len >= 0x00FF)
1788                &&(p_t2t->new_ndef_msg_len < 0x00FF)  )
1789            {
1790                p_t2t->ndef_msg_offset -= 2;
1791            }
1792            else if (  (p_t2t->new_ndef_msg_len >= 0x00FF)
1793                     &&(p_t2t->ndef_msg_len < 0x00FF)  )
1794            {
1795                p_t2t->ndef_msg_offset += 2;
1796            }
1797            p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
1798        }
1799        rw_t2t_handle_op_complete ();
1800        (*rw_cb.p_cback) (RW_T2T_NDEF_WRITE_EVT, (tRW_DATA *) &evt_data);
1801    }
1802}
1803
1804/*******************************************************************************
1805**
1806** Function         rw_t2t_get_tag_size
1807**
1808** Description      This function calculates tag data area size from data read
1809**                  from block with version number
1810**
1811** Returns          TMS of the tag
1812**
1813*******************************************************************************/
1814static UINT8 rw_t2t_get_tag_size (UINT8 *p_data)
1815{
1816    UINT16  LchunkSize = 0;
1817    UINT16  Num_LChuncks = 0;
1818    UINT16  tms = 0;
1819
1820    LchunkSize   = (UINT16) p_data[2] << 8 | p_data[3];
1821    Num_LChuncks = (UINT16) p_data[4] << 8 | p_data[5];
1822
1823    tms = (UINT16) (LchunkSize * Num_LChuncks);
1824
1825    tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
1826
1827    tms /= 0x08;
1828
1829    return (UINT8) tms;
1830}
1831
1832/*******************************************************************************
1833**
1834** Function         rw_t2t_handle_config_tag_readonly
1835**
1836** Description      This function handles configure type 2 tag as read only
1837**
1838** Returns          none
1839**
1840*******************************************************************************/
1841static void rw_t2t_handle_config_tag_readonly (UINT8 *p_data)
1842{
1843    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1844    tNFC_STATUS status  = NFC_STATUS_FAILED;
1845    BOOLEAN     b_notify = FALSE;
1846    UINT8       write_block[T2T_BLOCK_SIZE];
1847    tRW_DATA    evt;
1848    BOOLEAN     b_pending = FALSE;
1849    UINT8       read_lock = 0;
1850    UINT8       num_locks = 0;
1851    UINT16      offset;
1852
1853    switch (p_t2t->substate)
1854    {
1855    case RW_T2T_SUBSTATE_WAIT_READ_CC:
1856
1857        /* First soft lock the tag */
1858        rw_t2t_soft_lock_tag ();
1859
1860        break;
1861
1862    case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1863
1864        /* Successfully soft locked! Update Tag header for future reference */
1865        p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1866        if (!p_t2t->b_hard_lock)
1867        {
1868            /* Tag configuration complete */
1869            status   = NFC_STATUS_OK;
1870            b_notify = TRUE;
1871            break;
1872        }
1873
1874        /* Coverity: [FALSE-POSITIVE error] intended fall through */
1875        /* Missing break statement between cases in switch statement */
1876        /* fall through */
1877    case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
1878
1879        num_locks = 0;
1880
1881        while (num_locks < p_t2t->num_lockbytes)
1882        {
1883            if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_UPDATE_INITIATED)
1884            {
1885                /* Update control block as one or more dynamic lock byte (s) are set */
1886                p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1887            }
1888            if (!b_pending && p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED)
1889            {
1890                /* One or more dynamic lock bits are not set */
1891                b_pending = TRUE;
1892                read_lock = num_locks;
1893            }
1894            num_locks++;
1895        }
1896
1897        if (b_pending)
1898        {
1899            /* Read the block where dynamic lock bits are present to avoid writing to NDEF bytes in the same block */
1900            offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset + p_t2t->lockbyte[read_lock].byte_index;
1901            p_t2t->substate    = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1902            status = rw_t2t_read ((UINT16) (offset / T2T_BLOCK_LEN));
1903        }
1904        else
1905        {
1906            /* Now set Static lock bits as no more dynamic lock bits to set */
1907
1908            /* Copy the internal bytes */
1909            memcpy (write_block, &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN], T2T_INTERNAL_BYTES_LEN);
1910            /* Set all Static lock bits */
1911            write_block [T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1912            write_block [T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1913            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1914            status = rw_t2t_write ((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1915        }
1916        break;
1917
1918    case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1919        /* Now set the dynamic lock bits present in the block read now */
1920        status = rw_t2t_set_dynamic_lock_bits (p_data);
1921        break;
1922
1923    case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1924        /* Tag configuration complete */
1925        status   = NFC_STATUS_OK;
1926        b_notify = TRUE;
1927        break;
1928
1929    }
1930
1931    if (status != NFC_STATUS_OK || b_notify)
1932    {
1933        /* Notify upper layer the result of Configuring Tag as Read only */
1934        evt.status      = status;
1935        rw_t2t_handle_op_complete ();
1936        (*rw_cb.p_cback) (RW_T2T_SET_TAG_RO_EVT, (tRW_DATA *) &evt);
1937    }
1938}
1939
1940/*******************************************************************************
1941**
1942** Function         rw_t2t_handle_format_tag_rsp
1943**
1944** Description      This function handles formating a type 2 tag
1945**
1946** Returns          none
1947**
1948*******************************************************************************/
1949static void rw_t2t_handle_format_tag_rsp (UINT8 *p_data)
1950{
1951    tRW_DATA    evt;
1952    UINT8       *p;
1953    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
1954    tNFC_STATUS status  = NFC_STATUS_FAILED;
1955    UINT16      version_no;
1956    const       tT2T_INIT_TAG *p_ret;
1957    UINT8       tms;
1958    UINT8       next_block = T2T_FIRST_DATA_BLOCK + 1;
1959    UINT16      addr, locked_area;
1960    BOOLEAN     b_notify = FALSE;
1961
1962
1963    p = p_t2t->ndef_final_block;
1964    UINT8_TO_BE_STREAM (p, p_t2t->tlv_value[2]);
1965
1966    switch (p_t2t->substate)
1967    {
1968    case RW_T2T_SUBSTATE_WAIT_READ_CC:
1969        /* Start format operation */
1970        status = rw_t2t_format_tag ();
1971        break;
1972
1973    case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1974
1975        memcpy (p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1976        p_t2t->b_read_data = TRUE;
1977        version_no = (UINT16) p_data[0] << 8 | p_data[1];
1978        if ((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], TRUE, version_no)) != NULL)
1979        {
1980            /* Valid Version Number */
1981            if (p_ret->b_calc_cc)
1982                /* Calculate tag size from Version Information */
1983                tms = rw_t2t_get_tag_size (p_data);
1984
1985            else
1986                /* Tag size from Look up table */
1987                tms = p_ret->tms;
1988
1989            /* Set CC with the Tag size from look up table or from calculated value */
1990            status = rw_t2t_set_cc (tms);
1991        }
1992        break;
1993
1994    case RW_T2T_SUBSTATE_WAIT_SET_CC:
1995
1996        version_no = (UINT16) p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1997        if (  (version_no == 0)
1998            ||((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], TRUE, version_no)) == NULL)
1999            ||(!p_ret->b_multi_version)
2000            ||(!p_ret->b_calc_cc)  )
2001        {
2002            /* Currently Formating a non blank tag or a blank tag with manufacturer
2003             * has only one variant of tag. Set Null NDEF TLV and complete Format Operation */
2004            next_block = T2T_FIRST_DATA_BLOCK;
2005            p = p_t2t->ndef_final_block;
2006        }
2007        else
2008        {
2009            addr        = (UINT16) (((UINT16) p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) * ((UINT16) p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) + T2T_STATIC_SIZE);
2010            locked_area = ((UINT16) p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) * ((UINT16) p_t2t->tag_data[6]);
2011
2012            if ((status = rw_t2t_set_lock_tlv (addr, p_t2t->tag_data[7], locked_area)) == NFC_STATUS_REJECTED)
2013            {
2014                /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format Operation */
2015                next_block = T2T_FIRST_DATA_BLOCK;
2016                p = p_t2t->ndef_final_block;
2017            }
2018            else
2019                break;
2020        }
2021
2022        /* falls through */
2023    case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
2024
2025        /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
2026        UINT8_TO_BE_STREAM (p, TAG_NDEF_TLV);
2027        UINT8_TO_BE_STREAM (p, 0);
2028
2029        if (  ((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], FALSE, 0)) != NULL)
2030            &&(!p_ret->b_otp)  )
2031        {
2032            UINT8_TO_BE_STREAM (p, TAG_TERMINATOR_TLV);
2033        }
2034        else
2035            UINT8_TO_BE_STREAM (p, 0);
2036
2037        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
2038        /* send WRITE-E8 command */
2039        if ((status = rw_t2t_write (next_block, p_t2t->ndef_final_block)) == NFC_STATUS_OK)
2040            p_t2t->b_read_data = FALSE;
2041        break;
2042
2043    case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
2044        /* Tag Formated successfully */
2045        status   = NFC_STATUS_OK;
2046        b_notify = TRUE;
2047        break;
2048
2049    default:
2050        break;
2051
2052    }
2053
2054    if (status != NFC_STATUS_OK || b_notify)
2055    {
2056        /* Notify upper layer the result of Format op */
2057        evt.status      = status;
2058        rw_t2t_handle_op_complete ();
2059        (*rw_cb.p_cback) (RW_T2T_FORMAT_CPLT_EVT, (tRW_DATA *) &evt);
2060    }
2061
2062}
2063
2064/*******************************************************************************
2065**
2066** Function         rw_t2t_update_attributes
2067**
2068** Description      This function will update attribute for the current segment
2069**                  based on lock and reserved bytes
2070**
2071** Returns          None
2072**
2073*******************************************************************************/
2074static void rw_t2t_update_attributes (void)
2075{
2076    UINT8       count = 0;
2077    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2078    UINT16      lower_offset;
2079    UINT16      upper_offset;
2080    UINT16      offset;
2081    UINT8       num_bytes;
2082
2083    /* Prepare attr for the current segment */
2084    memset (p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof (UINT8));
2085
2086    /* calculate offset where the current segment starts in the tag */
2087    lower_offset   = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
2088    /* calculate offset where the current segment ends in the tag */
2089    upper_offset   = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
2090
2091
2092    /* check offset of lock bytes in the tag and update p_t2t->attr
2093     * for every lock byte that is present in the current segment */
2094    count = 0;
2095    while (count < p_t2t->num_lockbytes)
2096    {
2097        offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset + p_t2t->lockbyte[count].byte_index;
2098        if (offset >= lower_offset && offset < upper_offset)
2099        {
2100            /* Calculate offset in the current segment as p_t2t->attr is prepared for one segment only */
2101            offset %= RW_T2T_SEGMENT_BYTES;
2102            /* Every bit in p_t2t->attr indicates one byte of the tag is either a lock/reserved byte or not
2103             * So, each array element in p_t2t->attr covers two blocks in the tag as T2 block size is 4 and array element size is 8
2104             * Set the corresponding bit in attr to indicate - reserved byte */
2105            p_t2t->attr[offset / TAG_BITS_PER_BYTE] |= rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
2106        }
2107        count++;
2108    }
2109
2110
2111    /* Search reserved bytes identified by all memory tlvs present in the tag */
2112    count = 0;
2113    while (count < p_t2t->num_mem_tlvs)
2114    {
2115        /* check the offset of reserved bytes in the tag and update  p_t2t->attr
2116         * for every  reserved byte that is present in the current segment */
2117        num_bytes = 0;
2118        while (num_bytes < p_t2t->mem_tlv[count].num_bytes)
2119        {
2120            offset = p_t2t->mem_tlv[count].offset + num_bytes;
2121            if (offset >= lower_offset && offset < upper_offset)
2122            {
2123                /* Let offset represents offset in the current segment as p_t2t->attr is prepared for one segment only */
2124                offset %= RW_T2T_SEGMENT_BYTES;
2125                /* Every bit in p_t2t->attr indicates one byte of the tag is either a lock/reserved byte or not
2126                 * So, each array element in p_t2t->attr covers two blocks in the tag as T2 block size is 4 and array element size is 8
2127                 * Set the corresponding bit in attr to indicate - reserved byte */
2128                p_t2t->attr[offset /TAG_BITS_PER_BYTE] |= rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
2129            }
2130            num_bytes++;
2131        }
2132        count++;
2133    }
2134}
2135
2136/*******************************************************************************
2137**
2138** Function         rw_t2t_get_lock_bits_for_segment
2139**
2140** Description      This function returns the offset of lock bits associated for
2141**                  the specified segment
2142**
2143** Parameters:      segment: The segment number to which lock bits are associated
2144**                  p_start_byte: The offset of lock byte that contains the first
2145**                                lock bit for the segment
2146**                  p_start_bit:  The offset of the lock bit in the lock byte
2147**
2148**                  p_end_byte:   The offset of the last bit associcated to the
2149**                                segment
2150**
2151** Returns          Total number of lock bits assigned to the specified segment
2152**
2153*******************************************************************************/
2154static UINT8 rw_t2t_get_lock_bits_for_segment (UINT8 segment, UINT8 *p_start_byte, UINT8 *p_start_bit, UINT8 *p_end_byte)
2155{
2156    UINT8       total_bits = 0;
2157    UINT16      byte_count = 0;
2158    UINT16      lower_offset, upper_offset;
2159    UINT8       num_dynamic_locks = 0;
2160    UINT8       bit_count  = 0;
2161    UINT8       bytes_locked_per_bit;
2162    UINT8       num_bits;
2163    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2164    BOOLEAN     b_all_bits_are_locks = TRUE;
2165    UINT16      tag_size;
2166    UINT8       xx;
2167
2168    tag_size      = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) + (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
2169
2170    for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2171        tag_size += p_t2t->mem_tlv[xx].num_bytes;
2172
2173    lower_offset  = segment * RW_T2T_SEGMENT_BYTES;
2174    if (segment == 0)
2175    {
2176        lower_offset  += T2T_STATIC_SIZE;
2177    }
2178    upper_offset  = (segment + 1) * RW_T2T_SEGMENT_BYTES;
2179
2180    byte_count = T2T_STATIC_SIZE;
2181    if (tag_size < upper_offset)
2182    {
2183        upper_offset = tag_size;
2184    }
2185
2186    *p_start_byte = num_dynamic_locks;
2187    *p_start_bit  = 0;
2188
2189    while (  (byte_count <= lower_offset)
2190           &&(num_dynamic_locks < p_t2t->num_lockbytes)  )
2191    {
2192        bytes_locked_per_bit = p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index].bytes_locked_per_bit;
2193        /* Number of bits in the current lock byte */
2194        b_all_bits_are_locks = ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index].num_bits);
2195        num_bits             =  b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2196
2197        if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset)
2198        {
2199            /* Skip this lock byte as it covers different segment */
2200            byte_count += bytes_locked_per_bit * num_bits;
2201            num_dynamic_locks++;
2202        }
2203        else
2204        {
2205            bit_count = 0;
2206            while (bit_count < num_bits)
2207            {
2208                byte_count += bytes_locked_per_bit;
2209                if (byte_count > lower_offset)
2210                {
2211                    /* First lock bit that is used to lock this segment */
2212                    *p_start_byte = num_dynamic_locks;
2213                    *p_end_byte   = num_dynamic_locks;
2214                    *p_start_bit  = bit_count;
2215                    bit_count++;
2216                    total_bits    = 1;
2217                    break;
2218                }
2219                bit_count++;
2220            }
2221        }
2222    }
2223    if (num_dynamic_locks == p_t2t->num_lockbytes)
2224    {
2225        return 0;
2226    }
2227    while (  (byte_count < upper_offset)
2228           &&(num_dynamic_locks < p_t2t->num_lockbytes)  )
2229    {
2230        bytes_locked_per_bit = p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index].bytes_locked_per_bit;
2231        /* Number of bits in the current lock byte */
2232        b_all_bits_are_locks = ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index].num_bits);
2233        num_bits             =  b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2234
2235        if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count < upper_offset)
2236        {
2237            /* Collect all lock bits that covers the current segment */
2238            byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2239            total_bits += num_bits - bit_count;
2240            bit_count   = 0;
2241            *p_end_byte = num_dynamic_locks;
2242            num_dynamic_locks++;
2243        }
2244        else
2245        {
2246            /* The last lock byte that covers the current segment */
2247            bit_count = 0;
2248            while (bit_count < num_bits)
2249            {
2250                /* The last lock bit that is used to lock this segment */
2251                byte_count += bytes_locked_per_bit;
2252                if (byte_count >= upper_offset)
2253                {
2254                    *p_end_byte = num_dynamic_locks;
2255                    total_bits  += (bit_count + 1);
2256                    break;
2257                }
2258                bit_count++;
2259            }
2260        }
2261    }
2262    return total_bits;
2263}
2264
2265/*******************************************************************************
2266**
2267** Function         rw_t2t_update_lock_attributes
2268**
2269** Description      This function will check if the tag index passed as
2270**                  argument is a locked byte and return TRUE or FALSE
2271**
2272** Parameters:      index, the index of the byte in the tag
2273**
2274**
2275** Returns          TRUE, if the specified index in the tag is a locked or
2276**                        reserved or otp byte
2277**                  FALSE, otherwise
2278**
2279*******************************************************************************/
2280static void rw_t2t_update_lock_attributes (void)
2281{
2282    tRW_T2T_CB  *p_t2t                      = &rw_cb.tcb.t2t;
2283    UINT8       xx                          = 0;
2284    UINT8       num_static_lock_bytes       = 0;
2285    UINT8       num_dyn_lock_bytes          = 0;
2286    UINT8       bits_covered                = 0;
2287    UINT8       bytes_covered               = 0;
2288    UINT8       block_count                 = 0;
2289    BOOLEAN     b_all_bits_are_locks        = TRUE;
2290    UINT8       bytes_locked_per_lock_bit;
2291    UINT8       start_lock_byte;
2292    UINT8       start_lock_bit;
2293    UINT8       end_lock_byte;
2294    UINT8       num_lock_bits;
2295    UINT8       total_bits;
2296
2297
2298    /* Prepare lock_attr for the current segment */
2299    memset (p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof (UINT8));
2300
2301    block_count                 = 0;
2302    if (p_t2t->segment == 0)
2303    {
2304        /* Update lock_attributes based on static lock bytes */
2305        xx                      = 0;
2306        num_static_lock_bytes   = 0;
2307        block_count             = 0;
2308        num_lock_bits           = TAG_BITS_PER_BYTE;
2309
2310        while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES)
2311        {
2312            /* Update lock attribute based on 2 static locks */
2313            while (xx < num_lock_bits)
2314            {
2315                p_t2t->lock_attr[block_count] = 0x00;
2316
2317                if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] & rw_t2t_mask_bits[xx++])
2318                {
2319                    /* If the bit is set then 1 block is locked */
2320                    p_t2t->lock_attr[block_count] = 0x0F;
2321                }
2322
2323                if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] & rw_t2t_mask_bits[xx++])
2324                {
2325                    /* If the bit is set then 1 block is locked */
2326                    p_t2t->lock_attr[block_count] |= 0xF0;
2327                }
2328                block_count++;
2329            }
2330            num_static_lock_bytes++;
2331            xx = 0;
2332        }
2333        /* UID is always locked, irrespective of the lock value */
2334        p_t2t->lock_attr[0x00] = 0xFF;
2335    }
2336
2337    /* Get lock bits applicable for the current segment */
2338    if ((total_bits = rw_t2t_get_lock_bits_for_segment (p_t2t->segment,&start_lock_byte, &start_lock_bit, &end_lock_byte)) != 0)
2339    {
2340        /* update lock_attributes based on current segment using dynamic lock bytes */
2341        xx                            = start_lock_bit;
2342        num_dyn_lock_bytes            = start_lock_byte;
2343        bits_covered                  = 0;
2344        bytes_covered                 = 0;
2345        num_lock_bits                 = TAG_BITS_PER_BYTE;
2346        p_t2t->lock_attr[block_count] = 0;
2347
2348        while (num_dyn_lock_bytes <= end_lock_byte)
2349        {
2350            bytes_locked_per_lock_bit  = p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index].bytes_locked_per_bit;
2351            /* Find number of bits in the byte are lock bits */
2352            b_all_bits_are_locks = ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index].num_bits);
2353            num_lock_bits        =  b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2354
2355            while (xx < num_lock_bits)
2356            {
2357                bytes_covered = 0;
2358                while (bytes_covered < bytes_locked_per_lock_bit)
2359                {
2360                    if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte & rw_t2t_mask_bits[xx])
2361                    {
2362                        /* If the bit is set then it is locked */
2363                        p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
2364                    }
2365                    bytes_covered++;
2366                    bits_covered++;
2367                    if (bits_covered == TAG_BITS_PER_BYTE)
2368                    {
2369                        /* Move to next 8 bytes */
2370                        bits_covered = 0;
2371                        block_count++;
2372                        /* Assume unlocked before updating using locks */
2373                        if (block_count < RW_T2T_SEGMENT_SIZE)
2374                            p_t2t->lock_attr[block_count] = 0;
2375                    }
2376                }
2377                xx++;
2378            }
2379            num_dyn_lock_bytes++;
2380            xx = 0;
2381        }
2382    }
2383}
2384
2385/*******************************************************************************
2386**
2387** Function         rw_t2t_is_lock_res_byte
2388**
2389** Description      This function will check if the tag index passed as
2390**                  argument is a lock or reserved or otp byte and return
2391**                  TRUE or FALSE
2392**
2393** Parameters:      index, the index of the byte in the tag
2394**
2395**
2396** Returns          TRUE, if the specified index in the tag is a locked or
2397**                        reserved or otp byte
2398**                  FALSE, otherwise
2399**
2400*******************************************************************************/
2401static BOOLEAN rw_t2t_is_lock_res_byte (UINT16 index)
2402{
2403    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2404
2405    p_t2t->segment = (UINT8) (index / RW_T2T_SEGMENT_BYTES);
2406
2407    if (p_t2t->attr_seg != p_t2t->segment)
2408    {
2409        /* Update attributes for the current segment */
2410        rw_t2t_update_attributes ();
2411        p_t2t->attr_seg = p_t2t->segment;
2412    }
2413
2414    index = index % RW_T2T_SEGMENT_BYTES;
2415    /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a lock/reserved byte or not
2416     * So, each array element in p_t2t->attr covers two blocks in the tag as T2 block size is 4 and array element size is 8
2417     * Find the block and offset for the index (passed as argument) and Check if the offset bit in the
2418     * p_t2t->attr[block/2] is set or not. If the bit is set then it is a lock/reserved byte, otherwise not */
2419
2420    return ((p_t2t->attr[index /8] & rw_t2t_mask_bits[index % 8]) == 0) ? FALSE:TRUE;
2421}
2422
2423/*******************************************************************************
2424**
2425** Function         rw_t2t_is_read_only_byte
2426**
2427** Description      This function will check if the tag index passed as
2428**                  argument is a locked and return
2429**                  TRUE or FALSE
2430**
2431** Parameters:      index, the index of the byte in the tag
2432**
2433**
2434** Returns          TRUE, if the specified index in the tag is a locked or
2435**                        reserved or otp byte
2436**                  FALSE, otherwise
2437**
2438*******************************************************************************/
2439static BOOLEAN rw_t2t_is_read_only_byte (UINT16 index)
2440{
2441    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2442
2443    p_t2t->segment = (UINT8) (index / RW_T2T_SEGMENT_BYTES);
2444
2445    if (p_t2t->lock_attr_seg != p_t2t->segment)
2446    {
2447        /* Update lock attributes for the current segment */
2448        rw_t2t_update_lock_attributes ();
2449        p_t2t->lock_attr_seg = p_t2t->segment;
2450    }
2451
2452    index = index % RW_T2T_SEGMENT_BYTES;
2453    /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a read only byte or read write byte
2454     * So, each array element in p_t2t->lock_attr covers two blocks of the tag as T2 block size is 4 and array element size is 8
2455     * Find the block and offset for the index (passed as argument) and Check if the offset bit in
2456     * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a read only byte, otherwise read write byte */
2457
2458    return ((p_t2t->lock_attr[index /8] & rw_t2t_mask_bits[index % 8]) == 0) ? FALSE:TRUE;
2459}
2460
2461/*******************************************************************************
2462**
2463** Function         rw_t2t_set_dynamic_lock_bits
2464**
2465** Description      This function will set dynamic lock bits as part of
2466**                  configuring tag as read only
2467**
2468** Returns
2469**                  NFC_STATUS_OK, Command sent to set dynamic lock bits
2470**                  NFC_STATUS_FAILED: otherwise
2471**
2472*******************************************************************************/
2473tNFC_STATUS rw_t2t_set_dynamic_lock_bits (UINT8 *p_data)
2474{
2475    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2476    UINT8       write_block[T2T_BLOCK_SIZE];
2477    UINT16      offset;
2478    UINT16      next_offset;
2479    UINT8       num_bits;
2480    UINT8       next_num_bits;
2481    tNFC_STATUS status      = NFC_STATUS_FAILED;
2482    UINT8       num_locks;
2483    UINT8       lock_count;
2484    BOOLEAN     b_all_bits_are_locks = TRUE;
2485
2486    num_locks = 0;
2487
2488    memcpy (write_block, p_data, T2T_BLOCK_SIZE);
2489    while (num_locks < p_t2t->num_lockbytes)
2490    {
2491        if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED)
2492        {
2493            offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset + p_t2t->lockbyte[num_locks].byte_index;
2494
2495            /* Check if all bits are lock bits in the byte */
2496            b_all_bits_are_locks = ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2497            num_bits             =  b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2498
2499            write_block[(UINT8) (offset%T2T_BLOCK_SIZE)] |=  tags_pow (2,num_bits) - 1;
2500            lock_count = num_locks + 1;
2501
2502            /* Set all the lock bits in the block using a sing block write command */
2503            while (lock_count < p_t2t->num_lockbytes)
2504            {
2505                next_offset          = p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset + p_t2t->lockbyte[lock_count].byte_index;
2506
2507                /* Check if all bits are lock bits in the byte */
2508                b_all_bits_are_locks = ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2509                next_num_bits        = b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2510
2511                if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE)
2512                {
2513                    write_block[(UINT8) (next_offset % T2T_BLOCK_SIZE)] |=  tags_pow (2, next_num_bits) - 1;
2514                }
2515                else
2516                    break;
2517                lock_count ++;
2518            }
2519
2520            p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2521            /* send WRITE command to set dynamic lock bits */
2522            if ((status = rw_t2t_write ((UINT16) (offset / T2T_BLOCK_SIZE), write_block)) == NFC_STATUS_OK)
2523            {
2524                while (lock_count >  num_locks)
2525                {
2526                    /* Set update initiated flag to indicate a write command is sent to set dynamic lock bits of the block */
2527                    p_t2t->lockbyte[lock_count - 1].lock_status = RW_T2T_LOCK_UPDATE_INITIATED;
2528                    lock_count --;
2529                }
2530            }
2531            else
2532                status = NFC_STATUS_FAILED;
2533
2534            break;
2535
2536        }
2537        num_locks++;
2538    }
2539
2540    return status;
2541}
2542
2543/*******************************************************************************
2544**
2545** Function         rw_t2t_set_lock_tlv
2546**
2547** Description      This function will set lock control tlv on the blank
2548**                  activated type 2 tag based on values read from version block
2549**
2550** Parameters:      TAG data memory size
2551**
2552** Returns
2553**                  NFC_STATUS_OK, Command sent to set Lock TLV
2554**                  NFC_STATUS_FAILED: otherwise
2555**
2556*******************************************************************************/
2557tNFC_STATUS rw_t2t_set_lock_tlv (UINT16 addr, UINT8 num_dyn_lock_bits, UINT16 locked_area_size)
2558{
2559    tNFC_STATUS status  = NFC_STATUS_FAILED;
2560    INT8        PageAddr = 0;
2561    INT8        BytePerPage = 0;
2562    INT8        ByteOffset = 0;
2563    UINT8       a;
2564    UINT8       data_block[T2T_BLOCK_SIZE];
2565    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
2566    UINT8       *p;
2567    UINT8       xx;
2568
2569    for (xx = 15; xx >0; xx--)
2570    {
2571        a  = (UINT8) (addr / xx);
2572        a += (addr % xx) ? 1:0;
2573
2574        BytePerPage = (INT8) tags_log2 (a);
2575        ByteOffset  = (INT8) (addr - xx * tags_pow (2, BytePerPage));
2576
2577        if (ByteOffset < 16)
2578        {
2579            PageAddr = xx;
2580            break;
2581        }
2582    }
2583
2584    if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16))
2585    {
2586        memset (data_block, 0, T2T_BLOCK_SIZE);
2587        p = data_block;
2588        UINT8_TO_BE_STREAM (p, T2T_TLV_TYPE_LOCK_CTRL);
2589        UINT8_TO_BE_STREAM (p, T2T_TLEN_LOCK_CTRL_TLV);
2590        UINT8_TO_BE_STREAM (p, (PageAddr << 4 | ByteOffset));
2591        UINT8_TO_BE_STREAM (p, num_dyn_lock_bits);
2592
2593        p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2594        p_t2t->tlv_value[1] = num_dyn_lock_bits;
2595        p_t2t->tlv_value[2] = (UINT8) (BytePerPage << 4 | tags_log2 (locked_area_size));
2596
2597        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
2598
2599        /* send WRITE-E8 command */
2600        if ((status = rw_t2t_write (T2T_FIRST_DATA_BLOCK, data_block)) == NFC_STATUS_OK)
2601        {
2602            p_t2t->b_read_data = FALSE;
2603        }
2604        else
2605            p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2606    }
2607    else
2608        status = NFC_STATUS_REJECTED;
2609
2610    return status;
2611}
2612
2613/*******************************************************************************
2614**
2615** Function         rw_t2t_set_cc
2616**
2617** Description      This function will set Capability Container on the activated
2618**                  type 2 tag with default values of CC0, CC1, CC4 and specified
2619**                  CC3 value
2620**
2621** Parameters:      CC3 value of the tag
2622**
2623** Returns
2624**                  NFC_STATUS_OK, Command sent to set CC
2625**                  NFC_STATUS_FAILED: otherwise
2626**
2627*******************************************************************************/
2628tNFC_STATUS rw_t2t_set_cc (UINT8 tms)
2629{
2630    UINT8               cc_block[T2T_BLOCK_SIZE];
2631    tRW_T2T_CB          *p_t2t  = &rw_cb.tcb.t2t;
2632    tNFC_STATUS         status  = NFC_STATUS_FAILED;
2633    UINT8               *p;
2634
2635    memset (cc_block, 0, T2T_BLOCK_SIZE);
2636    memset (p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2637    p = cc_block;
2638
2639    /* Prepare Capability Container */
2640    UINT8_TO_BE_STREAM (p, T2T_CC0_NMN);
2641    UINT8_TO_BE_STREAM (p, T2T_CC1_VNO);
2642    UINT8_TO_BE_STREAM (p, tms);
2643    UINT8_TO_BE_STREAM (p, T2T_CC3_RWA_RW);
2644
2645    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
2646
2647    /* send WRITE-E8 command */
2648    if ((status = rw_t2t_write (T2T_CC_BLOCK, cc_block)) == NFC_STATUS_OK)
2649    {
2650        p_t2t->state    = RW_T2T_STATE_FORMAT_TAG;
2651        p_t2t->b_read_hdr = FALSE;
2652    }
2653    else
2654        p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2655
2656    return status;
2657}
2658
2659/*******************************************************************************
2660**
2661** Function         rw_t2t_format_tag
2662**
2663** Description      This function will format tag based on Manufacturer ID
2664**
2665** Returns
2666**                  NFC_STATUS_OK, Command sent to format Tag
2667**                  NFC_STATUS_FAILED: otherwise
2668**
2669*******************************************************************************/
2670tNFC_STATUS rw_t2t_format_tag (void)
2671{
2672    tRW_T2T_CB          *p_t2t  = &rw_cb.tcb.t2t;
2673    const tT2T_INIT_TAG *p_ret;
2674    UINT8               tms;
2675    tNFC_STATUS         status  = NFC_STATUS_FAILED;
2676    BOOLEAN             b_blank_tag = TRUE;
2677
2678    if ((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], FALSE, 0)) == NULL)
2679    {
2680        RW_TRACE_WARNING1 ("rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the tag!", p_t2t->tag_hdr[0]);
2681        return (NFC_STATUS_REJECTED);
2682    }
2683
2684    if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0)
2685    {
2686        /* If OTP tag has valid NDEF Message, cannot format the tag */
2687        if (  (p_t2t->ndef_msg_len > 0)
2688            &&(p_ret->b_otp)  )
2689        {
2690            RW_TRACE_WARNING0 ("rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2691            return (NFC_STATUS_FAILED);
2692        }
2693
2694        if (  ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) && (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN))
2695            ||((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) && (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) && (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) && (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO)) )
2696        {
2697            RW_TRACE_WARNING0 ("rw_t2t_format_tag - Tag not blank to Format!");
2698            return (NFC_STATUS_FAILED);
2699        }
2700        else
2701        {
2702            tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2703            b_blank_tag = FALSE;
2704        }
2705    }
2706    else
2707        tms = p_ret->tms;
2708
2709    memset (p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2710
2711    if (!b_blank_tag || !p_ret->b_multi_version)
2712    {
2713        status = rw_t2t_set_cc (tms);
2714    }
2715    else if (p_ret->version_block != 0)
2716    {
2717        /* If Version number is not read, READ it now */
2718        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2719
2720        if ((status = rw_t2t_read (p_ret->version_block)) == NFC_STATUS_OK)
2721            p_t2t->state    = RW_T2T_STATE_FORMAT_TAG;
2722        else
2723            p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2724    }
2725    else
2726    {
2727        /* UID block is the version block */
2728        p_t2t->state    = RW_T2T_STATE_FORMAT_TAG;
2729        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2730        rw_t2t_handle_format_tag_rsp (p_t2t->tag_hdr);
2731    }
2732
2733    return status;
2734}
2735
2736/*******************************************************************************
2737**
2738** Function         rw_t2t_soft_lock_tag
2739**
2740** Description      This function will soft lock the tag after validating CC.
2741**
2742** Returns
2743**                  NFC_STATUS_OK, Command sent to soft lock the tag
2744**                  NFC_STATUS_FAILED: otherwise
2745**
2746*******************************************************************************/
2747tNFC_STATUS rw_t2t_soft_lock_tag (void)
2748{
2749    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
2750    tNFC_STATUS status  = NFC_STATUS_FAILED;
2751    UINT8       write_block[T2T_BLOCK_SIZE];
2752    UINT8       num_locks;
2753
2754    /* If CC block is read and cc3 is soft locked, reject the command */
2755    if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
2756    {
2757        RW_TRACE_ERROR1 ("rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: %u", p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2758        return (NFC_STATUS_FAILED);
2759    }
2760
2761    if (p_t2t->b_hard_lock)
2762    {
2763        /* Should have performed NDEF Detection on dynamic memory structure tag, before permanently converting to Read only
2764         * Even when no lock control tlv is present, default lock bytes should be present */
2765
2766        if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) && (p_t2t->num_lockbytes == 0))
2767        {
2768            RW_TRACE_ERROR0 ("rw_t2t_soft_lock_tag: Error: Lock TLV not detected! Cannot hard lock the tag");
2769            return (NFC_STATUS_FAILED);
2770        }
2771
2772        /* On dynamic memory structure tag, reset all lock bytes status to 'Not Updated' if not in Updated status */
2773        num_locks = 0;
2774        while (num_locks < p_t2t->num_lockbytes)
2775        {
2776            if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2777                p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2778            num_locks++;
2779        }
2780    }
2781
2782    memcpy (write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2783    write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
2784
2785    p_t2t->substate    = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2786    /* First Soft lock the tag */
2787    if ((status = rw_t2t_write (T2T_CC_BLOCK, write_block)) == NFC_STATUS_OK)
2788    {
2789        p_t2t->state        = RW_T2T_STATE_SET_TAG_RO;
2790        p_t2t->b_read_hdr   = FALSE;
2791    }
2792    else
2793    {
2794        p_t2t->substate     = RW_T2T_SUBSTATE_NONE;
2795    }
2796    return status;
2797}
2798
2799/*****************************************************************************
2800**
2801** Function         RW_T2tFormatNDef
2802**
2803** Description
2804**      Format Tag content
2805**
2806** Returns
2807**      NFC_STATUS_OK, Command sent to format Tag
2808**      NFC_STATUS_FAILED: otherwise
2809**
2810*****************************************************************************/
2811tNFC_STATUS RW_T2tFormatNDef (void)
2812{
2813    tRW_T2T_CB          *p_t2t  = &rw_cb.tcb.t2t;
2814    tNFC_STATUS         status  = NFC_STATUS_FAILED;
2815
2816    if (p_t2t->state != RW_T2T_STATE_IDLE)
2817    {
2818        RW_TRACE_WARNING1 ("RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u", p_t2t->state);
2819        return (NFC_STATUS_FAILED);
2820    }
2821
2822    if (!p_t2t->b_read_hdr)
2823    {
2824        /* If UID is not read, READ it now */
2825        p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2826
2827        if ((status = rw_t2t_read (0)) == NFC_STATUS_OK)
2828            p_t2t->state    = RW_T2T_STATE_FORMAT_TAG;
2829        else
2830            p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2831    }
2832    else
2833        status = rw_t2t_format_tag ();
2834
2835    return status;
2836}
2837
2838/*******************************************************************************
2839**
2840** Function         RW_T2tLocateTlv
2841**
2842** Description      This function is used to perform TLV detection on a Type 2
2843**                  tag, and retrieve the tag's TLV attribute information.
2844**
2845**                  Before using this API, the application must call
2846**                  RW_SelectTagType to indicate that a Type 2 tag has been
2847**                  activated.
2848**
2849** Parameters:      tlv_type : TLV to detect
2850**
2851** Returns          NCI_STATUS_OK, if detection was started. Otherwise, error status.
2852**
2853*******************************************************************************/
2854tNFC_STATUS RW_T2tLocateTlv (UINT8 tlv_type)
2855{
2856    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2857    tNFC_STATUS status;
2858    UINT16      block;
2859
2860    if (p_t2t->state != RW_T2T_STATE_IDLE)
2861    {
2862        RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
2863        return (NFC_STATUS_BUSY);
2864    }
2865
2866    if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) && (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV))
2867    {
2868        RW_TRACE_API1 ("RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
2869        return (NFC_STATUS_FAILED);
2870    }
2871
2872    if (  (tlv_type == TAG_LOCK_CTRL_TLV)
2873        &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)  )
2874    {
2875        RW_TRACE_API1 ("RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x", p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2876        return (NFC_STATUS_FAILED);
2877    }
2878
2879    if (  (tlv_type == TAG_NDEF_TLV)
2880        &&(p_t2t->b_read_hdr)
2881        &&(p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)  )
2882    {
2883        RW_TRACE_WARNING3 ("RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: 0x%02x, CC[3]: 0x%02x", p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE], p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2884        return (NFC_STATUS_FAILED);
2885    }
2886
2887    p_t2t->work_offset = 0;
2888    p_t2t->tlv_detect  = tlv_type;
2889
2890    /* Reset control block variables based on type of tlv to detect */
2891    if (tlv_type == TAG_LOCK_CTRL_TLV)
2892    {
2893        p_t2t->num_lockbytes    = 0;
2894        p_t2t->num_lock_tlvs    = 0;
2895    }
2896    else if (tlv_type == TAG_MEM_CTRL_TLV)
2897    {
2898        p_t2t->num_mem_tlvs     = 0;
2899    }
2900    else if (tlv_type == TAG_NDEF_TLV)
2901    {
2902        p_t2t->ndef_msg_offset  = 0;
2903        p_t2t->num_lockbytes    = 0;
2904        p_t2t->num_lock_tlvs    = 0;
2905        p_t2t->num_mem_tlvs     = 0;
2906        p_t2t->ndef_msg_len     = 0;
2907        p_t2t->ndef_status      = T2T_NDEF_NOT_DETECTED;
2908    }
2909    else
2910    {
2911        p_t2t->prop_msg_len     = 0;
2912    }
2913
2914    if (!p_t2t->b_read_hdr)
2915    {
2916        /* First read CC block */
2917        block                   = 0;
2918        p_t2t->substate         = RW_T2T_SUBSTATE_WAIT_READ_CC;
2919    }
2920    else
2921    {
2922        /* Read first data block */
2923        block                   = T2T_FIRST_DATA_BLOCK;
2924        p_t2t->substate         = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2925    }
2926
2927    /* Start reading tag, looking for the specified TLV */
2928    if ((status = rw_t2t_read ((UINT16) block)) == NFC_STATUS_OK)
2929    {
2930        p_t2t->state    = RW_T2T_STATE_DETECT_TLV;
2931    }
2932    else
2933    {
2934        p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2935    }
2936    return (status);
2937}
2938
2939/*******************************************************************************
2940**
2941** Function         RW_T2tDetectNDef
2942**
2943** Description      This function is used to perform NDEF detection on a Type 2
2944**                  tag, and retrieve the tag's NDEF attribute information.
2945**
2946**                  Before using this API, the application must call
2947**                  RW_SelectTagType to indicate that a Type 2 tag has been
2948**                  activated.
2949**
2950** Parameters:      none
2951**
2952** Returns          NCI_STATUS_OK,if detect op started.Otherwise,error status.
2953**
2954*******************************************************************************/
2955tNFC_STATUS RW_T2tDetectNDef (void)
2956{
2957    return RW_T2tLocateTlv (TAG_NDEF_TLV);
2958}
2959
2960/*******************************************************************************
2961**
2962** Function         RW_T2tReadNDef
2963**
2964** Description      Retrieve NDEF contents from a Type2 tag.
2965**
2966**                  The RW_T2T_NDEF_READ_EVT event is used to notify the
2967**                  application after reading the NDEF message.
2968**
2969**                  Before using this API, the RW_T2tDetectNDef function must
2970**                  be called to verify that the tag contains NDEF data, and to
2971**                  retrieve the NDEF attributes.
2972**
2973**                  Internally, this command will be separated into multiple Tag2
2974**                  Read commands (if necessary) - depending on the NDEF Msg size
2975**
2976** Parameters:      p_buffer:   The buffer into which to read the NDEF message
2977**                  buf_len:    The length of the buffer
2978**
2979** Returns          NCI_STATUS_OK, if read was started. Otherwise, error status.
2980**
2981*******************************************************************************/
2982tNFC_STATUS RW_T2tReadNDef (UINT8 *p_buffer, UINT16 buf_len)
2983{
2984    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
2985    tNFC_STATUS status = NFC_STATUS_OK;
2986    UINT16      block;
2987
2988    if (p_t2t->state != RW_T2T_STATE_IDLE)
2989    {
2990        RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
2991        return (NFC_STATUS_FAILED);
2992    }
2993
2994    if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED)
2995    {
2996        RW_TRACE_ERROR0 ("RW_T2tReadNDef - Error: NDEF detection not performed yet");
2997        return (NFC_STATUS_FAILED);
2998    }
2999
3000    if (buf_len < p_t2t->ndef_msg_len)
3001    {
3002        RW_TRACE_WARNING2 ("RW_T2tReadNDef - buffer size: %u  less than NDEF msg sise: %u", buf_len, p_t2t->ndef_msg_len);
3003        return (NFC_STATUS_FAILED);
3004    }
3005
3006    if (!p_t2t->ndef_msg_len)
3007    {
3008        RW_TRACE_WARNING1 ("RW_T2tReadNDef - NDEF Message length is zero ", p_t2t->ndef_msg_len);
3009        return (NFC_STATUS_NOT_INITIALIZED);
3010    }
3011
3012    p_t2t->p_ndef_buffer  = p_buffer;
3013    p_t2t->work_offset    = 0;
3014
3015    block  = (UINT16) (p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
3016    block -= block % T2T_READ_BLOCKS;
3017
3018    p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3019
3020    if (  (block == T2T_FIRST_DATA_BLOCK)
3021        &&(p_t2t->b_read_data)  )
3022    {
3023        p_t2t->state        = RW_T2T_STATE_READ_NDEF;
3024        p_t2t->block_read   = T2T_FIRST_DATA_BLOCK;
3025        rw_t2t_handle_ndef_read_rsp (p_t2t->tag_data);
3026    }
3027    else
3028    {
3029        /* Start reading NDEF Message */
3030        if ((status = rw_t2t_read (block)) == NFC_STATUS_OK)
3031        {
3032            p_t2t->state    = RW_T2T_STATE_READ_NDEF;
3033        }
3034    }
3035
3036    return (status);
3037}
3038
3039/*******************************************************************************
3040**
3041** Function         RW_T2tWriteNDef
3042**
3043** Description      Write NDEF contents to a Type2 tag.
3044**
3045**                  Before using this API, the RW_T2tDetectNDef
3046**                  function must be called to verify that the tag contains
3047**                  NDEF data, and to retrieve the NDEF attributes.
3048**
3049**                  The RW_T2T_NDEF_WRITE_EVT callback event will be used to
3050**                  notify the application of the response.
3051**
3052**                  Internally, this command will be separated into multiple Tag2
3053**                  Write commands (if necessary) - depending on the NDEF Msg size
3054**
3055** Parameters:      msg_len:    The length of the buffer
3056**                  p_msg:      The NDEF message to write
3057**
3058** Returns          NCI_STATUS_OK,if write was started. Otherwise, error status
3059**
3060*******************************************************************************/
3061tNFC_STATUS RW_T2tWriteNDef (UINT16 msg_len, UINT8 *p_msg)
3062{
3063    tRW_T2T_CB  *p_t2t          = &rw_cb.tcb.t2t;
3064    UINT16      block;
3065    const       tT2T_INIT_TAG *p_ret;
3066
3067    tNFC_STATUS status          = NFC_STATUS_OK;
3068
3069    if (p_t2t->state != RW_T2T_STATE_IDLE)
3070    {
3071        RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
3072        return (NFC_STATUS_FAILED);
3073    }
3074
3075    if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW)
3076    {
3077        RW_TRACE_ERROR1 ("RW_T2tWriteNDef - Write access not granted - CC3: %u", p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
3078        return (NFC_STATUS_REFUSED);
3079    }
3080
3081    if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED)
3082    {
3083        RW_TRACE_ERROR0 ("RW_T2tWriteNDef - Error: NDEF detection not performed!");
3084        return (NFC_STATUS_FAILED);
3085    }
3086
3087    /* Check if there is enough memory on the tag */
3088    if (msg_len > p_t2t->max_ndef_msg_len)
3089    {
3090        RW_TRACE_ERROR1 ("RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes", p_t2t->max_ndef_msg_len);
3091        return (NFC_STATUS_FAILED);
3092    }
3093
3094    /* If OTP tag and tag has valid NDEF Message, stop writting new NDEF Message as it may corrupt the tag */
3095    if (  (p_t2t->ndef_msg_len > 0)
3096        &&((p_ret = t2t_tag_init_data (p_t2t->tag_hdr[0], FALSE, 0)) != NULL)
3097        &&(p_ret->b_otp)  )
3098    {
3099        RW_TRACE_WARNING0 ("RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
3100        return (NFC_STATUS_FAILED);
3101    }
3102    p_t2t->p_new_ndef_buffer = p_msg;
3103    p_t2t->new_ndef_msg_len  = msg_len;
3104    p_t2t->work_offset       = 0;
3105
3106    p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
3107    /* Read first NDEF Block before updating NDEF */
3108
3109    block = (UINT16) (p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
3110
3111    if (  (block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS))
3112        &&(p_t2t->b_read_data)  )
3113    {
3114        p_t2t->state        = RW_T2T_STATE_WRITE_NDEF;
3115        p_t2t->block_read   = block;
3116        rw_t2t_handle_ndef_write_rsp (&p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
3117    }
3118    else
3119    {
3120        if ((status = rw_t2t_read (block)) == NFC_STATUS_OK)
3121            p_t2t->state    = RW_T2T_STATE_WRITE_NDEF;
3122        else
3123            p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3124    }
3125
3126    return status;
3127}
3128
3129/*******************************************************************************
3130**
3131** Function         RW_T2tSetTagReadOnly
3132**
3133** Description      This function can be called to set T2 tag as read only.
3134**
3135** Parameters:      b_hard_lock:   To indicate hard lock the tag or not
3136**
3137** Returns          NCI_STATUS_OK, if setting tag as read only was started.
3138**                  Otherwise, error status.
3139**
3140*******************************************************************************/
3141tNFC_STATUS RW_T2tSetTagReadOnly (BOOLEAN b_hard_lock)
3142{
3143    tNFC_STATUS status = NFC_STATUS_FAILED;
3144    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
3145
3146    if (p_t2t->state != RW_T2T_STATE_IDLE)
3147    {
3148        RW_TRACE_ERROR1 ("RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
3149        return (NFC_STATUS_FAILED);
3150    }
3151
3152    p_t2t->b_hard_lock = b_hard_lock;
3153
3154    if (!p_t2t->b_read_hdr)
3155    {
3156        /* Read CC block before configuring tag as Read only */
3157        p_t2t->substate    = RW_T2T_SUBSTATE_WAIT_READ_CC;
3158        if ((status = rw_t2t_read ((UINT16) 0)) == NFC_STATUS_OK)
3159        {
3160            p_t2t->state    = RW_T2T_STATE_SET_TAG_RO;
3161        }
3162        else
3163            p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3164    }
3165    else
3166        status = rw_t2t_soft_lock_tag ();
3167
3168    return status;
3169}
3170
3171#endif /* (defined ((RW_NDEF_INCLUDED) && (RW_NDEF_INCLUDED == TRUE)) */
3172
3173#endif /* (NFC_INCLUDED == TRUE) */
3174