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