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