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