rw_t1t_ndef.c revision 5c65c3a0f42e174e47fecd4e569606003217ff4e
1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/******************************************************************************
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  Copyright (C) 2010-2013 Broadcom Corporation
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  Licensed under the Apache License, Version 2.0 (the "License");
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  you may not use this file except in compliance with the License.
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  You may obtain a copy of the License at:
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  http://www.apache.org/licenses/LICENSE-2.0
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  Unless required by applicable law or agreed to in writing, software
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  distributed under the License is distributed on an "AS IS" BASIS,
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  See the License for the specific language governing permissions and
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  limitations under the License.
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ******************************************************************************/
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/******************************************************************************
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  This file contains the implementation for Type 1 tag NDEF operation in
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *  Reader/Writer mode.
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ******************************************************************************/
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <string.h>
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "nfc_target.h"
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if (NFC_INCLUDED == TRUE)
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "nfc_api.h"
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "nci_hmsgs.h"
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "rw_api.h"
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "rw_int.h"
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "nfc_int.h"
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "gki.h"
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if (defined (RW_NDEF_INCLUDED) && (RW_NDEF_INCLUDED == TRUE))
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/* Local Functions */
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic tNFC_STATUS rw_t1t_handle_rall_rsp (BOOLEAN *p_notify,UINT8 *p_data);
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic tNFC_STATUS rw_t1t_handle_dyn_read_rsp (BOOLEAN *p_notify, UINT8 *p_data);
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic tNFC_STATUS rw_t1t_handle_write_rsp (BOOLEAN *p_notify, UINT8 *p_data);
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic tNFC_STATUS rw_t1t_handle_read_rsp (BOOLEAN *p_callback, UINT8 *p_data);
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic tNFC_STATUS rw_t1t_handle_tlv_detect_rsp (UINT8 *p_data);
45static tNFC_STATUS rw_t1t_handle_ndef_read_rsp (UINT8 *p_data);
46static tNFC_STATUS rw_t1t_handle_ndef_write_rsp (UINT8 *p_data);
47static tNFC_STATUS rw_t1t_handle_ndef_rall_rsp (void);
48static tNFC_STATUS rw_t1t_ndef_write_first_block (void);
49static tNFC_STATUS rw_t1t_next_ndef_write_block (void);
50static tNFC_STATUS rw_t1t_send_ndef_byte (UINT8 data, UINT8 block, UINT8 index, UINT8 msg_len);
51static tNFC_STATUS rw_t1t_send_ndef_block (UINT8 *p_data, UINT8 block);
52static UINT8 rw_t1t_prepare_ndef_bytes (UINT8 *p_data, UINT8 *p_length_field, UINT8 *p_index, BOOLEAN b_one_byte, UINT8 block, UINT8 lengthfield_len);
53static UINT8 rw_t1t_get_ndef_flags (void);
54static UINT16 rw_t1t_get_ndef_max_size (void);
55static BOOLEAN rw_t1t_is_lock_reserved_otp_byte (UINT16 index);
56static BOOLEAN rw_t1t_is_read_only_byte (UINT16 index);
57static UINT8 rw_t1t_get_lock_bits_for_segment (UINT8 segment,UINT8 *p_start_byte, UINT8 *p_start_bit,UINT8 *p_end_byte);
58static void rw_t1t_update_attributes (void);
59static void rw_t1t_update_lock_attributes (void);
60static void rw_t1t_extract_lock_bytes (UINT8 *p_data);
61static void rw_t1t_update_tag_state (void);
62
63const UINT8 rw_t1t_mask_bits[8] =
64{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
65
66/*******************************************************************************
67**
68** Function         rw_t1t_handle_rsp
69**
70** Description      This function handles the response received for all commands
71**                  sent to tag
72**
73** Returns          event to be sent to application
74**
75*******************************************************************************/
76tRW_EVENT rw_t1t_handle_rsp (const tT1T_CMD_RSP_INFO * p_info, BOOLEAN *p_notify, UINT8 *p_data, tNFC_STATUS *p_status)
77{
78    tRW_EVENT   rw_event;
79    tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
80    UINT8       adds;
81
82    if(  (p_t1t->state == RW_T1T_STATE_READ)
83       ||(p_t1t->state == RW_T1T_STATE_WRITE)  )
84    {
85        return t1t_info_to_evt (p_info);
86    }
87
88    rw_event = rw_t1t_info_to_event (p_info);
89
90    if (p_info->opcode == T1T_CMD_RALL)
91    {
92        *p_status = rw_t1t_handle_rall_rsp (p_notify,p_data);
93    }
94    else if (p_info->opcode == T1T_CMD_RSEG)
95    {
96        adds = *p_data;
97        if (adds == 0)
98        {
99            p_t1t->b_rseg   = TRUE;
100            rw_t1t_update_tag_state ();
101            rw_t1t_update_attributes ();
102            rw_t1t_update_lock_attributes ();
103            memcpy (p_t1t->mem, (UINT8 *) (p_data + T1T_ADD_LEN), T1T_SEGMENT_SIZE);
104        }
105        *p_status = rw_t1t_handle_dyn_read_rsp (p_notify,p_data);
106    }
107    else if (p_info->opcode == T1T_CMD_READ8)
108    {
109        *p_status = rw_t1t_handle_dyn_read_rsp (p_notify,p_data);
110    }
111    else
112    {
113        *p_status = rw_t1t_handle_write_rsp (p_notify,p_data);
114    }
115    return rw_event;
116}
117
118/*******************************************************************************
119**
120** Function         rw_t1t_info_to_event
121**
122** Description      This function returns RW event code based on the current state
123**
124** Returns          RW event code
125**
126*******************************************************************************/
127tRW_EVENT rw_t1t_info_to_event (const tT1T_CMD_RSP_INFO * p_info)
128{
129    tRW_EVENT   rw_event;
130    tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
131
132    switch (p_t1t->state)
133    {
134    case RW_T1T_STATE_TLV_DETECT:
135        if (p_t1t->tlv_detect == TAG_NDEF_TLV)
136            rw_event = RW_T1T_NDEF_DETECT_EVT;
137        else
138            rw_event = RW_T1T_TLV_DETECT_EVT;
139        break;
140
141    case RW_T1T_STATE_READ_NDEF:
142        rw_event = RW_T1T_NDEF_READ_EVT;
143        break;
144
145    case RW_T1T_STATE_WRITE_NDEF:
146        rw_event = RW_T1T_NDEF_WRITE_EVT;
147        break;
148
149    case RW_T1T_STATE_SET_TAG_RO:
150        rw_event = RW_T1T_SET_TAG_RO_EVT;
151        break;
152
153    case RW_T1T_STATE_CHECK_PRESENCE:
154        rw_event = RW_T1T_PRESENCE_CHECK_EVT;
155        break;
156
157    case RW_T1T_STATE_FORMAT_TAG:
158        rw_event = RW_T1T_FORMAT_CPLT_EVT;
159        break;
160
161    default:
162	    rw_event = t1t_info_to_evt (p_info);
163        break;
164    }
165    return rw_event;
166}
167
168/*******************************************************************************
169**
170** Function         rw_t1t_extract_lock_bytes
171**
172** Description      This function will extract lock bytes if any present in the
173**                  response data
174**
175** Parameters       p_data: Data bytes in the response of RSEG/READ8/RALL command
176**
177** Returns          None
178**
179*******************************************************************************/
180void rw_t1t_extract_lock_bytes (UINT8 *p_data)
181{
182    UINT16              end;
183    UINT16              start;
184    UINT8               num_locks;
185    UINT16              lock_offset = 0;
186    UINT16              offset;
187    tRW_T1T_CB          *p_t1t          = &rw_cb.tcb.t1t;
188    tT1T_CMD_RSP_INFO   *p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) rw_cb.tcb.t1t.p_cmd_rsp_info;
189
190    num_locks = 0;
191    /* Based on the Command used to read Tag, calculate the offset of the tag read */
192    if (p_cmd_rsp_info->opcode == T1T_CMD_RSEG)
193    {
194        start = p_t1t->segment * T1T_SEGMENT_SIZE;
195        end   = start + T1T_SEGMENT_SIZE;
196    }
197    else if (p_cmd_rsp_info->opcode == T1T_CMD_READ8)
198    {
199        start = p_t1t->block_read * T1T_BLOCK_SIZE;
200        end   = start + T1T_BLOCK_SIZE;
201    }
202    else if (p_cmd_rsp_info->opcode == T1T_CMD_RALL)
203    {
204        start = 0;
205        end   = T1T_STATIC_SIZE;
206    }
207    else
208        return;
209
210    /* Collect lock bytes that are present in the part of the data read from Tag */
211    while (num_locks < p_t1t->num_lockbytes)
212    {
213        if (p_t1t->lockbyte[num_locks].b_lock_read == FALSE)
214        {
215            /* Get the exact offset of the dynamic lock byte in the tag */
216            offset = p_t1t->lock_tlv[p_t1t->lockbyte[num_locks].tlv_index].offset + p_t1t->lockbyte[num_locks].byte_index;
217            if (  (offset <  end)
218                &&(offset >= start)  )
219
220            {
221                /* This dynamic lock byte is in the response */
222                if (p_cmd_rsp_info->opcode == T1T_CMD_RSEG)
223                {
224                    lock_offset = (offset % T1T_SEGMENT_SIZE);
225                }
226                else if (p_cmd_rsp_info->opcode == T1T_CMD_READ8)
227                {
228                    lock_offset = (offset % T1T_BLOCK_SIZE);
229                }
230                else if (p_cmd_rsp_info->opcode == T1T_CMD_RALL)
231                {
232                    lock_offset = offset;
233                }
234
235                p_t1t->lockbyte[num_locks].lock_byte    = p_data[lock_offset];
236                p_t1t->lockbyte[num_locks].b_lock_read  = TRUE;
237            }
238            else
239                break;
240        }
241        num_locks++;
242    }
243}
244
245/*******************************************************************************
246**
247** Function         rw_t1t_update_tag_attributes
248**
249** Description      This function will update tag attributes based on cc, ndef
250**                  message length
251**
252** Returns          None
253**
254*******************************************************************************/
255void rw_t1t_update_tag_state (void)
256{
257    tRW_T1T_CB  *p_t1t          = &rw_cb.tcb.t1t;
258
259    /* Set Tag state based on CC value and NDEF Message length */
260    if (  ((p_t1t->mem[T1T_CC_NMN_BYTE] == T1T_CC_NMN) || (p_t1t->mem[T1T_CC_NMN_BYTE] == 0))
261        &&((p_t1t->mem[T1T_CC_VNO_BYTE] == T1T_CC_VNO) || (p_t1t->mem[T1T_CC_VNO_BYTE] == T1T_CC_LEGACY_VNO))
262        &&((p_t1t->mem[T1T_CC_RWA_BYTE] == T1T_CC_RWA_RW) || (p_t1t->mem[T1T_CC_RWA_BYTE] == T1T_CC_RWA_RO))  )
263    {
264        /* Valid CC value, so Tag is initialized */
265        if (p_t1t->ndef_msg_len > 0)
266        {
267            if (p_t1t->mem[T1T_CC_RWA_BYTE] == T1T_CC_RWA_RO)
268            {
269                /* NDEF Message presence, CC indication sets Tag as READ ONLY  */
270                p_t1t->tag_attribute = RW_T1_TAG_ATTRB_READ_ONLY;
271            }
272            else if (p_t1t->mem[T1T_CC_RWA_BYTE] == T1T_CC_RWA_RW)
273            {
274                /* NDEF Message presence, CC indication sets Tag as READ WRITE */
275                p_t1t->tag_attribute = RW_T1_TAG_ATTRB_READ_WRITE;
276            }
277        }
278        else
279        {
280            /* If NDEF is not yet detected then Tag remains in Initialized state
281            *  after NDEF Detection the Tag state may be updated */
282            p_t1t->tag_attribute = RW_T1_TAG_ATTRB_INITIALIZED;
283        }
284    }
285    else
286    {
287        p_t1t->tag_attribute = RW_T1_TAG_ATTRB_UNKNOWN;
288    }
289}
290
291/*******************************************************************************
292**
293** Function         rw_t1t_read_locks
294**
295** Description      This function will send command to read next unread locks
296**
297** Returns          NFC_STATUS_OK, if all locks are read successfully
298**                  NFC_STATUS_FAILED, if reading locks failed
299**                  NFC_STATUS_CONTINUE, if reading locks is in progress
300**
301*******************************************************************************/
302tNFC_STATUS rw_t1t_read_locks (void)
303{
304    UINT8       num_locks   = 0;
305    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
306    tNFC_STATUS status      = NFC_STATUS_CONTINUE;
307    UINT16      offset;
308
309    while (num_locks < p_t1t->num_lockbytes)
310    {
311        if (p_t1t->lockbyte[num_locks].b_lock_read == FALSE)
312        {
313            offset = p_t1t->lock_tlv[p_t1t->lockbyte[num_locks].tlv_index].offset + p_t1t->lockbyte[num_locks].byte_index;
314            if (offset < T1T_STATIC_SIZE)
315            {
316               p_t1t->lockbyte[num_locks].lock_byte   = p_t1t->mem[offset];
317               p_t1t->lockbyte[num_locks].b_lock_read = TRUE;
318            }
319            else if (offset < (p_t1t->mem[T1T_CC_TMS_BYTE] + 1) * T1T_BLOCK_SIZE)
320            {
321                /* send READ8 command */
322                p_t1t->block_read = (UINT8) (offset/T1T_BLOCK_SIZE);
323                if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_READ8, p_t1t->block_read, NULL)) == NFC_STATUS_OK)
324                {
325                    /* Reading Locks */
326                    status          = NFC_STATUS_CONTINUE;
327                    p_t1t->substate = RW_T1T_SUBSTATE_WAIT_READ_LOCKS;
328                }
329                break;
330            }
331            else
332            {
333                /* Read locks failed */
334                status = NFC_STATUS_FAILED;
335                break;
336            }
337        }
338        num_locks++;
339    }
340    if (num_locks == p_t1t->num_lockbytes)
341    {
342        /* All locks are read */
343        status = NFC_STATUS_OK;
344    }
345
346    return status;
347}
348
349/*******************************************************************************
350**
351** Function         rw_t1t_handle_write_rsp
352**
353** Description      This function handles response received for WRITE_E8,
354**                  WRITE_NE8, WRITE_E, WRITE_NE commands
355**
356** Returns          status of the current NDEF/TLV Operation
357**
358*******************************************************************************/
359static tNFC_STATUS rw_t1t_handle_write_rsp (BOOLEAN *p_notify, UINT8 *p_data)
360{
361    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
362    tNFC_STATUS status      = NFC_STATUS_OK;
363    UINT8       num_locks;
364    UINT8       lock_count;
365    UINT8       value;
366    UINT8       addr;
367    UINT8       write_block[T1T_BLOCK_SIZE];
368    UINT16      offset;
369    UINT16      next_offset;
370    UINT8       num_bits;
371    UINT8       next_num_bits;
372
373    *p_notify = FALSE;
374
375    switch (p_t1t->state)
376    {
377    case RW_T1T_STATE_WRITE:
378        *p_notify = TRUE;
379        break;
380
381    case RW_T1T_STATE_FORMAT_TAG:
382        if (p_t1t->substate == RW_T1T_SUBSTATE_WAIT_SET_NULL_NDEF)
383        {
384            if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN)
385                *p_notify = TRUE;
386            else
387            {
388                if (p_t1t->work_offset < (T1T_BLOCK_SIZE - 1))
389                {
390                    p_t1t->work_offset++;
391                    /* send WRITE-E command */
392                    RW_T1T_BLD_ADD ((addr), 1, (UINT8) p_t1t->work_offset);
393
394                    if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, p_t1t->ndef_first_block[(UINT8) p_t1t->work_offset])) != NFC_STATUS_OK)
395                        *p_notify = TRUE;
396                }
397                else
398                    *p_notify = TRUE;
399            }
400
401        }
402        else
403        {
404            /* send WRITE-E8 command */
405            if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_E8, 2, p_t1t->ndef_final_block)) != NFC_STATUS_OK)
406                *p_notify = TRUE;
407            else
408                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_NULL_NDEF;
409        }
410        break;
411
412    case RW_T1T_STATE_SET_TAG_RO:
413        switch (p_t1t->substate)
414        {
415        case RW_T1T_SUBSTATE_WAIT_SET_CC_RWA_RO:
416
417            if (!p_t1t->b_hard_lock)
418            {
419                status    = NFC_STATUS_OK;
420                *p_notify = TRUE;
421                break;
422            }
423
424            if ((p_t1t->hr[0] & 0x0F) != 1)
425            {
426                memset (write_block,0,T1T_BLOCK_SIZE);
427                write_block[0] = 0xFF;
428                write_block[1] = 0xFF;
429
430                /* send WRITE-NE8 command */
431                if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_NE8, T1T_LOCK_BLOCK, write_block)) != NFC_STATUS_OK)
432                    *p_notify       = TRUE;
433                else
434                    p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
435            }
436            else
437            {
438                /* send WRITE-NE command */
439                RW_T1T_BLD_ADD ((addr), (T1T_LOCK_BLOCK), (0));
440                if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_NE, addr, 0xFF)) != NFC_STATUS_OK)
441                    *p_notify       = TRUE;
442                else
443                    p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
444            }
445            break;
446
447        case RW_T1T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
448
449            /* send WRITE-NE command */
450            RW_T1T_BLD_ADD ((addr), (T1T_LOCK_BLOCK), (1));
451            if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_NE, addr, 0xFF)) != NFC_STATUS_OK)
452                *p_notify       = TRUE;
453            else
454                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
455
456            break;
457
458        case RW_T1T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
459            num_locks = 0;
460            while (num_locks < p_t1t->num_lockbytes)
461            {
462                if (p_t1t->lockbyte[num_locks].lock_status == RW_T1T_LOCK_UPDATE_INITIATED)
463                {
464                    p_t1t->lockbyte[num_locks].lock_status = RW_T1T_LOCK_UPDATED;
465                }
466                num_locks++;
467            }
468
469            num_locks = 0;
470            while (num_locks < p_t1t->num_lockbytes)
471            {
472                if (p_t1t->lockbyte[num_locks].lock_status == RW_T1T_LOCK_NOT_UPDATED)
473                {
474                    offset = p_t1t->lock_tlv[p_t1t->lockbyte[num_locks].tlv_index].offset + p_t1t->lockbyte[num_locks].byte_index;
475                    num_bits = ((p_t1t->lockbyte[num_locks].byte_index + 1)* 8 <= p_t1t->lock_tlv[p_t1t->lockbyte[num_locks].tlv_index].num_bits) ? 8 : p_t1t->lock_tlv[p_t1t->lockbyte[num_locks].tlv_index].num_bits % 8;
476
477                    if ((p_t1t->hr[0] & 0x0F) != 1)
478                    {
479                        memset (write_block,0,T1T_BLOCK_SIZE);
480
481                        write_block[(UINT8) (offset%T1T_BLOCK_SIZE)] |=  tags_pow (2,num_bits) - 1;
482                        lock_count = num_locks + 1;
483                        while (lock_count < p_t1t->num_lockbytes)
484                        {
485                            next_offset = p_t1t->lock_tlv[p_t1t->lockbyte[lock_count].tlv_index].offset + p_t1t->lockbyte[lock_count].byte_index;
486                            next_num_bits = ((p_t1t->lockbyte[lock_count].byte_index + 1)* 8 <= p_t1t->lock_tlv[p_t1t->lockbyte[lock_count].tlv_index].num_bits) ? 8 : p_t1t->lock_tlv[p_t1t->lockbyte[lock_count].tlv_index].num_bits % 8;
487
488                            if (next_offset/T1T_BLOCK_SIZE == offset/T1T_BLOCK_SIZE)
489                            {
490                                write_block[(UINT8) (next_offset%T1T_BLOCK_SIZE)] |=  tags_pow (2,next_num_bits) - 1;
491                            }
492                            else
493                                break;
494                            lock_count ++;
495                        }
496
497                        /* send WRITE-NE8 command */
498                        if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_NE8, (UINT8) (offset/T1T_BLOCK_SIZE), write_block)) == NFC_STATUS_OK)
499                        {
500                            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
501                            while (lock_count >  num_locks)
502                            {
503                                p_t1t->lockbyte[lock_count - 1].lock_status = RW_T1T_LOCK_UPDATE_INITIATED;
504                                lock_count --;
505                            }
506                        }
507                        else
508                            *p_notify       = TRUE;
509                    }
510                    else
511                    {
512                        /* send WRITE-NE command */
513                        RW_T1T_BLD_ADD ((addr), ((UINT8) (offset/T1T_BLOCK_SIZE)), ((UINT8) (offset%T1T_BLOCK_SIZE)));
514                        value = (UINT8) (tags_pow (2,num_bits) - 1);
515                        if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_NE, addr, value)) == NFC_STATUS_OK)
516                        {
517                            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
518                            p_t1t->lockbyte[num_locks].lock_status = RW_T1T_LOCK_UPDATE_INITIATED;
519                        }
520                        else
521                            *p_notify       = TRUE;
522                    }
523                    break;
524                }
525                num_locks++;
526            }
527            if (num_locks == p_t1t->num_lockbytes)
528            {
529                rw_t1t_update_lock_attributes ();
530                status    = NFC_STATUS_OK;
531                *p_notify = TRUE;
532            }
533            break;
534        }
535        break;
536
537    case RW_T1T_STATE_WRITE_NDEF:
538        switch (p_t1t->substate)
539        {
540        case RW_T1T_SUBSTATE_WAIT_VALIDATE_NDEF:
541            p_t1t->ndef_msg_len  = p_t1t->new_ndef_msg_len;
542            p_t1t->tag_attribute = RW_T1_TAG_ATTRB_READ_WRITE;
543            *p_notify = TRUE;
544            break;
545
546        case RW_T1T_SUBSTATE_WAIT_NDEF_UPDATED:
547            status      = rw_t1t_handle_ndef_write_rsp (p_data);
548            if (status == NFC_STATUS_OK)
549            {
550                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_VALIDATE_NDEF;
551            }
552            else if (status == NFC_STATUS_FAILED)
553            {
554                /* Send Negative response to upper layer */
555                *p_notify       = TRUE;
556            }
557            break;
558
559        case RW_T1T_SUBSTATE_WAIT_NDEF_WRITE:
560            status = rw_t1t_handle_ndef_write_rsp (p_data);
561
562            if (status == NFC_STATUS_FAILED)
563            {
564                /* Send Negative response to upper layer */
565                *p_notify       = TRUE;
566            }
567            else if (status == NFC_STATUS_OK)
568            {
569                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_NDEF_UPDATED;
570            }
571            break;
572
573        case RW_T1T_SUBSTATE_WAIT_INVALIDATE_NDEF:
574            status = rw_t1t_handle_ndef_write_rsp (p_data);
575            if (status == NFC_STATUS_FAILED)
576            {
577                /* Send Negative response to upper layer */
578                *p_notify   = TRUE;
579            }
580            else if (status == NFC_STATUS_CONTINUE)
581            {
582                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_NDEF_WRITE;
583            }
584            else
585            {
586                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_NDEF_UPDATED;
587            }
588            break;
589        }
590        break;
591    }
592    return status;
593}
594
595/*******************************************************************************
596**
597** Function         rw_t1t_handle_read_rsp
598**
599** Description      This function handle the data bytes excluding ADD(S)/ADD8 field
600**                  received as part of RSEG, RALL, READ8 command response
601**
602** Returns          status of the current NDEF/TLV Operation
603**
604*******************************************************************************/
605tNFC_STATUS rw_t1t_handle_read_rsp (BOOLEAN *p_notify, UINT8 *p_data)
606{
607    tRW_T1T_CB              *p_t1t  = &rw_cb.tcb.t1t;
608    tNFC_STATUS             status  = NFC_STATUS_OK;
609    tRW_DETECT_NDEF_DATA    ndef_data;
610    tRW_DETECT_TLV_DATA     tlv_data;
611    UINT8                   count;
612    tRW_READ_DATA           evt_data;
613
614    *p_notify = FALSE;
615    /* Handle the response based on the current state */
616    switch (p_t1t->state)
617    {
618    case RW_T1T_STATE_READ:
619        *p_notify = TRUE;
620        break;
621
622    case RW_T1T_STATE_READ_NDEF:
623        status = rw_t1t_handle_ndef_rall_rsp ();
624        if (status != NFC_STATUS_CONTINUE)
625        {
626            evt_data.status = status;
627            evt_data.p_data = NULL;
628            rw_t1t_handle_op_complete ();
629            (*rw_cb.p_cback) (RW_T1T_NDEF_READ_EVT, (tRW_DATA *) &evt_data);
630        }
631        break;
632
633    case RW_T1T_STATE_TLV_DETECT:
634        switch (p_t1t->substate)
635        {
636        case RW_T1T_SUBSTATE_WAIT_READ_LOCKS:
637            status = rw_t1t_read_locks ();
638            if (status != NFC_STATUS_CONTINUE)
639            {
640                rw_t1t_update_lock_attributes ();
641                /* Send positive response to upper layer */
642                if (p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV)
643                {
644                    tlv_data.protocol   = NFC_PROTOCOL_T1T;
645                    tlv_data.num_bytes  = p_t1t->num_lockbytes;
646                    tlv_data.status = status;
647                    rw_t1t_handle_op_complete ();
648                    (*rw_cb.p_cback) (RW_T1T_TLV_DETECT_EVT, (tRW_DATA *) &tlv_data);
649                }
650                else if (p_t1t->tlv_detect == TAG_NDEF_TLV)
651                {
652                    ndef_data.protocol  = NFC_PROTOCOL_T1T;
653                    ndef_data.flags     = rw_t1t_get_ndef_flags ();
654                    ndef_data.flags    |= RW_NDEF_FL_FORMATED;
655                    ndef_data.max_size  = (UINT32) rw_t1t_get_ndef_max_size ();
656                    ndef_data.cur_size  = p_t1t->ndef_msg_len;
657
658                    if (ndef_data.max_size  < ndef_data.cur_size)
659                    {
660                        ndef_data.flags    |= RW_NDEF_FL_READ_ONLY;
661                        ndef_data.max_size  = ndef_data.cur_size;
662                    }
663
664                    if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY))
665                    {
666                        ndef_data.flags    |= RW_NDEF_FL_SOFT_LOCKABLE;
667                        if (status == NFC_STATUS_OK)
668                            ndef_data.flags    |= RW_NDEF_FL_HARD_LOCKABLE;
669                    }
670                    ndef_data.status = status;
671                    rw_t1t_handle_op_complete ();
672                    (*rw_cb.p_cback) (RW_T1T_NDEF_DETECT_EVT, (tRW_DATA *)&ndef_data);
673                }
674            }
675            break;
676
677        case RW_T1T_SUBSTATE_NONE:
678            if (p_t1t->tlv_detect == TAG_MEM_CTRL_TLV)
679            {
680                tlv_data.status    = rw_t1t_handle_tlv_detect_rsp (p_t1t->mem);
681                tlv_data.protocol  = NFC_PROTOCOL_T1T;
682                tlv_data.num_bytes = 0;
683                count              = 0;
684                while (count < p_t1t->num_mem_tlvs)
685                {
686                    tlv_data.num_bytes += p_t1t->mem_tlv[p_t1t->num_mem_tlvs].num_bytes;
687                    count++;
688                }
689                rw_t1t_handle_op_complete ();
690                /* Send response to upper layer */
691                (*rw_cb.p_cback) (RW_T1T_TLV_DETECT_EVT, (tRW_DATA *) &tlv_data);
692            }
693            else if (p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV)
694            {
695                tlv_data.status    = rw_t1t_handle_tlv_detect_rsp (p_t1t->mem);
696                tlv_data.protocol  = NFC_PROTOCOL_T1T;
697                tlv_data.num_bytes = p_t1t->num_lockbytes;
698
699                if (tlv_data.status == NFC_STATUS_FAILED)
700                {
701                    rw_t1t_handle_op_complete ();
702
703                    /* Send Negative response to upper layer */
704                    (*rw_cb.p_cback) (RW_T1T_TLV_DETECT_EVT, (tRW_DATA *)&tlv_data);
705                }
706                else
707                {
708                    rw_t1t_extract_lock_bytes (p_data);
709                    status = rw_t1t_read_locks ();
710                    if (status != NFC_STATUS_CONTINUE)
711                    {
712                        /* Send positive response to upper layer */
713                        tlv_data.status = status;
714                        rw_t1t_handle_op_complete ();
715
716                        (*rw_cb.p_cback) (RW_T1T_TLV_DETECT_EVT, (tRW_DATA *) &tlv_data);
717                    }
718                }
719            }
720            else if (p_t1t->tlv_detect == TAG_NDEF_TLV)
721            {
722                ndef_data.protocol  = NFC_PROTOCOL_T1T;
723                ndef_data.flags     = rw_t1t_get_ndef_flags ();
724
725                if (p_t1t->mem[T1T_CC_NMN_BYTE] == T1T_CC_NMN)
726                {
727                    ndef_data.status    = rw_t1t_handle_tlv_detect_rsp (p_t1t->mem);
728
729                    ndef_data.cur_size  = p_t1t->ndef_msg_len;
730                    if (ndef_data.status == NFC_STATUS_FAILED)
731                    {
732                        ndef_data.max_size  = (UINT32) rw_t1t_get_ndef_max_size ();
733                        if (ndef_data.max_size  < ndef_data.cur_size)
734                        {
735                            ndef_data.flags    |= RW_NDEF_FL_READ_ONLY;
736                            ndef_data.max_size  = ndef_data.cur_size;
737                        }
738                        if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY))
739                        {
740                            ndef_data.flags    |= RW_NDEF_FL_SOFT_LOCKABLE;
741                        }
742                        /* Send Negative response to upper layer */
743                        rw_t1t_handle_op_complete ();
744
745                        (*rw_cb.p_cback) (RW_T1T_NDEF_DETECT_EVT, (tRW_DATA *) &ndef_data);
746                    }
747                    else
748                    {
749                        ndef_data.flags    |= RW_NDEF_FL_FORMATED;
750                        rw_t1t_extract_lock_bytes (p_data);
751                        status = rw_t1t_read_locks ();
752                        if (status != NFC_STATUS_CONTINUE)
753                        {
754                            ndef_data.max_size  = (UINT32) rw_t1t_get_ndef_max_size ();
755                            if (ndef_data.max_size  < ndef_data.cur_size)
756                            {
757                                ndef_data.flags    |= RW_NDEF_FL_READ_ONLY;
758                                ndef_data.max_size  = ndef_data.cur_size;
759                            }
760
761                            if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY))
762                            {
763                                ndef_data.flags    |= RW_NDEF_FL_SOFT_LOCKABLE;
764                                if (status == NFC_STATUS_OK)
765                                    ndef_data.flags    |= RW_NDEF_FL_HARD_LOCKABLE;
766                            }
767                            /* Send positive response to upper layer */
768                            ndef_data.status = status;
769                            rw_t1t_handle_op_complete ();
770
771                            (*rw_cb.p_cback) (RW_T1T_NDEF_DETECT_EVT, (tRW_DATA *)&ndef_data);
772                        }
773                    }
774                }
775                else
776                {
777                    /* Send Negative response to upper layer */
778                    ndef_data.status    = NFC_STATUS_FAILED;
779                    ndef_data.max_size  = (UINT32) rw_t1t_get_ndef_max_size ();
780                    ndef_data.cur_size  = p_t1t->ndef_msg_len;
781                    if (ndef_data.max_size  < ndef_data.cur_size)
782                    {
783                        ndef_data.flags    |= RW_NDEF_FL_READ_ONLY;
784                        ndef_data.max_size  = ndef_data.cur_size;
785                    }
786                    if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY))
787                    {
788                        ndef_data.flags    |= RW_NDEF_FL_SOFT_LOCKABLE;
789                        ndef_data.flags    |= RW_NDEF_FL_SOFT_LOCKABLE;
790                    }
791                    rw_t1t_handle_op_complete ();
792
793                    (*rw_cb.p_cback) (RW_T1T_NDEF_DETECT_EVT, (tRW_DATA *) &ndef_data);
794                }
795            }
796            break;
797        }
798        break;
799    }
800    return status;
801}
802
803/*******************************************************************************
804**
805** Function         rw_t1t_handle_dyn_read_rsp
806**
807** Description      This function handles response received for READ8, RSEG
808**                  commands based on the current state
809**
810** Returns          status of the current NDEF/TLV Operation
811**
812*******************************************************************************/
813static tNFC_STATUS rw_t1t_handle_dyn_read_rsp (BOOLEAN *p_notify, UINT8 *p_data)
814{
815    tNFC_STATUS status  = NFC_STATUS_OK;
816    tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
817
818    *p_notify = FALSE;
819
820    p_data += T1T_ADD_LEN;
821
822    rw_t1t_extract_lock_bytes (p_data);
823
824    if (p_t1t->state == RW_T1T_STATE_READ_NDEF)
825    {
826        status = rw_t1t_handle_ndef_read_rsp (p_data);
827        if (  (status == NFC_STATUS_FAILED)
828            ||(status == NFC_STATUS_OK)  )
829        {
830            /* Send response to upper layer */
831            *p_notify = TRUE;
832        }
833    }
834    else if (p_t1t->state == RW_T1T_STATE_WRITE_NDEF)
835    {
836        status = rw_t1t_handle_ndef_write_rsp (p_data);
837        if (status == NFC_STATUS_FAILED)
838        {
839            /* Send response to upper layer */
840            *p_notify = TRUE;
841        }
842        else if (status == NFC_STATUS_CONTINUE)
843        {
844            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_INVALIDATE_NDEF;
845        }
846    }
847    else
848    {
849        status = rw_t1t_handle_read_rsp (p_notify, p_data);
850    }
851    return status;
852}
853
854/*****************************************************************************
855**
856** Function         rw_t1t_handle_rall_rsp
857**
858** Description      Handle response to RALL - Collect CC, set Tag state
859**
860** Returns          None
861**
862*****************************************************************************/
863static tNFC_STATUS rw_t1t_handle_rall_rsp (BOOLEAN *p_notify,UINT8 *p_data)
864{
865    tRW_T1T_CB  *p_t1t   = &rw_cb.tcb.t1t;
866
867    p_data      += T1T_HR_LEN; /* skip HR */
868    memcpy (p_t1t->mem, (UINT8 *) p_data, T1T_STATIC_SIZE);
869    p_t1t->segment  = 0;
870    rw_t1t_extract_lock_bytes (p_data);
871
872    p_data      += T1T_UID_LEN + T1T_RES_BYTE_LEN; /* skip Block 0, UID and Reserved byte */
873
874    RW_TRACE_DEBUG0 ("rw_t1t_handle_rall_rsp ()");
875
876    rw_t1t_update_tag_state ();
877    rw_t1t_update_attributes ();
878    rw_t1t_update_lock_attributes ();
879    p_t1t->b_update = TRUE;
880    return (rw_t1t_handle_read_rsp (p_notify, p_t1t->mem));
881}
882
883/*******************************************************************************
884**
885** Function         rw_t1t_handle_tlv_detect_rsp
886**
887** Description      Handle response to the last command sent while
888**                  detecting tlv
889**
890** Returns          NFC_STATUS_OK, if tlv detect is complete & success
891**                  NFC_STATUS_FAILED,if tlv detect failed
892**
893*******************************************************************************/
894static tNFC_STATUS rw_t1t_handle_tlv_detect_rsp (UINT8 *p_data)
895{
896    UINT16      offset;
897    UINT16      len;
898    UINT8       xx;
899    UINT8       *p_readbytes;
900    UINT8       index;
901    UINT8       tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
902    UINT8       found_tlv = TAG_NULL_TLV;
903    tRW_T1T_CB  *p_t1t          = &rw_cb.tcb.t1t;
904    BOOLEAN     failed          = FALSE;
905    BOOLEAN     found           = FALSE;
906    UINT8       count           = 0;
907    tNFC_STATUS status          = NFC_STATUS_FAILED;
908    UINT8       start_offset    = T1T_UID_LEN + T1T_CC_LEN + T1T_RES_BYTE_LEN;
909    UINT8       end_offset      = T1T_STATIC_SIZE - (2*T1T_BLOCK_SIZE);
910    UINT8       bytes_read      = T1T_STATIC_SIZE;
911    UINT8       tlv_value[T1T_DEFAULT_TLV_LEN];
912    UINT16      bytes_count = 0;
913
914    p_readbytes = p_data;
915
916    for (offset = start_offset; offset < end_offset  && !failed && !found;)
917    {
918        if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) (offset)) == TRUE)
919        {
920            offset++;
921            continue;
922        }
923        switch (tlv_detect_state)
924        {
925        case RW_T1T_SUBSTATE_WAIT_TLV_DETECT:
926            /* Search for the tag */
927            found_tlv = p_readbytes[offset++];
928            switch (found_tlv)
929            {
930            case TAG_NULL_TLV:         /* May be used for padding. SHALL ignore this */
931                break;
932
933            case TAG_NDEF_TLV:
934                if (p_t1t->tlv_detect == TAG_NDEF_TLV)
935                {
936                    index = (offset % T1T_BLOCK_SIZE);
937                    /* Backup ndef first block */
938                    memcpy (&p_t1t->ndef_first_block[0],&p_readbytes[offset-index],index);
939                    memcpy (&p_t1t->ndef_first_block[index],&p_readbytes[offset],T1T_BLOCK_SIZE - index);
940                    tlv_detect_state = RW_T1T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
941                }
942                else if (p_t1t->tlv_detect == TAG_PROPRIETARY_TLV)
943                {
944                    tlv_detect_state = RW_T1T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
945                }
946                else if (  ((p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV) && (p_t1t->num_lockbytes > 0))
947                         ||((p_t1t->tlv_detect == TAG_MEM_CTRL_TLV) && (p_t1t->num_mem_tlvs > 0))  )
948                {
949                    found = TRUE;
950                }
951                else
952                {
953                    failed = TRUE;
954                }
955                break;
956
957            case TAG_LOCK_CTRL_TLV:
958            case TAG_MEM_CTRL_TLV:
959                tlv_detect_state = RW_T1T_SUBSTATE_WAIT_READ_TLV_LEN0;
960                break;
961
962            case TAG_PROPRIETARY_TLV:
963                if (p_t1t->tlv_detect == TAG_PROPRIETARY_TLV)
964                {
965                    index = (offset % T1T_BLOCK_SIZE);
966                    /* Backup ndef first block */
967                    tlv_detect_state = RW_T1T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
968                }
969                else
970                {
971                    /* NDEF/LOCK/MEM TLV can exist after Proprietary Tlv so we continue searching, skiping proprietary tlv */
972                    tlv_detect_state = RW_T1T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
973                }
974                break;
975
976            case TAG_TERMINATOR_TLV:   /* Last TLV block in the data area. Must be no NDEF nessage */
977                if (  ((p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV) && (p_t1t->num_lockbytes > 0))
978                    ||((p_t1t->tlv_detect == TAG_MEM_CTRL_TLV) && (p_t1t->num_mem_tlvs > 0))  )
979                {
980                    found = TRUE;
981                }
982                else
983                {
984                    failed = TRUE;
985                }
986                break;
987            default:
988                failed = TRUE;
989            }
990            break;
991
992        case RW_T1T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
993            len = p_readbytes[offset];
994            switch (found_tlv)
995            {
996            case TAG_NDEF_TLV:
997                p_t1t->ndef_header_offset = offset + p_t1t->work_offset;
998                if (len == T1T_LONG_NDEF_LEN_FIELD_BYTE0)
999                {
1000                    /* The next two bytes constitute length bytes */
1001                    tlv_detect_state     = RW_T1T_SUBSTATE_WAIT_READ_TLV_LEN0;
1002                }
1003                else
1004                {
1005                    /* one byte length field */
1006                    p_t1t->ndef_msg_len = len;
1007                    bytes_count  = p_t1t->ndef_msg_len;
1008                    tlv_detect_state     = RW_T1T_SUBSTATE_WAIT_READ_TLV_VALUE;
1009                }
1010                break;
1011
1012            case TAG_PROPRIETARY_TLV:
1013                if (len == 0xFF)
1014                {
1015                    /* The next two bytes constitute length bytes */
1016                    tlv_detect_state     = RW_T1T_SUBSTATE_WAIT_READ_TLV_LEN0;
1017                }
1018                else
1019                {
1020                    /* one byte length field */
1021                    bytes_count  = len;
1022                    tlv_detect_state     = RW_T1T_SUBSTATE_WAIT_READ_TLV_VALUE;
1023                }
1024                break;
1025            }
1026            offset++;
1027            break;
1028
1029        case RW_T1T_SUBSTATE_WAIT_READ_TLV_LEN0:
1030            switch (found_tlv)
1031            {
1032            case TAG_LOCK_CTRL_TLV:
1033            case TAG_MEM_CTRL_TLV:
1034
1035                len = p_readbytes[offset];
1036                if (len == T1T_DEFAULT_TLV_LEN)
1037                {
1038                    /* Valid Lock control TLV */
1039                    tlv_detect_state = RW_T1T_SUBSTATE_WAIT_READ_TLV_VALUE;
1040                    bytes_count = T1T_DEFAULT_TLV_LEN;
1041                }
1042                else if (  ((p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV) && (p_t1t->num_lockbytes > 0))
1043                         ||((p_t1t->tlv_detect == TAG_MEM_CTRL_TLV) && (p_t1t->num_mem_tlvs > 0))  )
1044                {
1045                    found = TRUE;
1046                }
1047                else
1048                {
1049                    failed = TRUE;
1050                }
1051                break;
1052
1053            case TAG_NDEF_TLV:
1054            case TAG_PROPRIETARY_TLV:
1055                /* The first length byte */
1056                bytes_count  = (UINT8) p_readbytes[offset];
1057                tlv_detect_state     = RW_T1T_SUBSTATE_WAIT_READ_TLV_LEN1;
1058                break;
1059            }
1060            offset++;
1061            break;
1062
1063        case RW_T1T_SUBSTATE_WAIT_READ_TLV_LEN1:
1064            bytes_count  = (bytes_count << 8) + p_readbytes[offset];
1065            if (found_tlv == TAG_NDEF_TLV)
1066            {
1067                p_t1t->ndef_msg_len = bytes_count;
1068            }
1069            tlv_detect_state     = RW_T1T_SUBSTATE_WAIT_READ_TLV_VALUE;
1070            offset++;
1071            break;
1072
1073        case RW_T1T_SUBSTATE_WAIT_READ_TLV_VALUE:
1074            switch (found_tlv)
1075            {
1076            case TAG_NDEF_TLV:
1077                if ((bytes_count == p_t1t->ndef_msg_len) && (p_t1t->tlv_detect == TAG_NDEF_TLV))
1078                {
1079                    /* The first byte offset after length field */
1080                    p_t1t->ndef_msg_offset = offset + p_t1t->work_offset;
1081                }
1082                if (bytes_count > 0)
1083                    bytes_count--;
1084
1085                if (p_t1t->tlv_detect == TAG_NDEF_TLV)
1086                {
1087                    if (p_t1t->ndef_msg_len > 0)
1088                    {
1089                        rw_t1t_update_tag_state ();
1090                    }
1091                    else
1092                    {
1093                        p_t1t->tag_attribute = RW_T1_TAG_ATTRB_INITIALIZED_NDEF;
1094                    }
1095                    found = TRUE;
1096                }
1097                else if (bytes_count == 0)
1098                {
1099                    tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
1100                }
1101                break;
1102
1103            case TAG_LOCK_CTRL_TLV:
1104                bytes_count--;
1105                if (  (p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV)
1106                    ||(p_t1t->tlv_detect == TAG_NDEF_TLV)  )
1107                {
1108                    tlv_value[2 - bytes_count] = p_readbytes[offset];
1109                    if (bytes_count == 0)
1110                    {
1111                        if (p_t1t->num_lock_tlvs < RW_T1T_MAX_LOCK_TLVS)
1112                        {
1113                            p_t1t->lock_tlv[p_t1t->num_lock_tlvs].offset   = (tlv_value[0] >> 4) & 0x0F;
1114                            p_t1t->lock_tlv[p_t1t->num_lock_tlvs].offset  *= (UINT8) tags_pow (2, tlv_value[2] & 0x0F);
1115                            p_t1t->lock_tlv[p_t1t->num_lock_tlvs].offset  += tlv_value[0] & 0x0F;
1116                            p_t1t->lock_tlv[p_t1t->num_lock_tlvs].bytes_locked_per_bit = (UINT8) tags_pow (2, ((tlv_value[2] & 0xF0) >> 4));
1117                            p_t1t->lock_tlv[p_t1t->num_lock_tlvs].num_bits = tlv_value[1];
1118                            count = tlv_value[1] / 8 + ((tlv_value[1] % 8 != 0)? 1:0);
1119                            xx = 0;
1120                            while (xx < count)
1121                            {
1122                                if (p_t1t->num_lockbytes < RW_T1T_MAX_LOCK_BYTES)
1123                                {
1124                                    p_t1t->lockbyte[p_t1t->num_lockbytes].tlv_index = p_t1t->num_lock_tlvs;
1125                                    p_t1t->lockbyte[p_t1t->num_lockbytes].byte_index = xx;
1126                                    p_t1t->lockbyte[p_t1t->num_lockbytes].b_lock_read = FALSE;
1127                                    p_t1t->num_lockbytes++;
1128                                }
1129                                else
1130                                    RW_TRACE_ERROR1 ("T1T Buffer overflow error. Max supported lock bytes=0x%02X", RW_T1T_MAX_LOCK_BYTES);
1131                                xx++;
1132                            }
1133                            p_t1t->num_lock_tlvs++;
1134                            rw_t1t_update_attributes ();
1135                        }
1136                        else
1137                            RW_TRACE_ERROR1 ("T1T Buffer overflow error. Max supported lock tlvs=0x%02X", RW_T1T_MAX_LOCK_TLVS);
1138
1139                        tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
1140                    }
1141                }
1142                else
1143                {
1144                    if (bytes_count == 0)
1145                    {
1146                        tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
1147                    }
1148                }
1149                break;
1150
1151            case TAG_MEM_CTRL_TLV:
1152                bytes_count--;
1153                if (  (p_t1t->tlv_detect == TAG_MEM_CTRL_TLV)
1154                    ||(p_t1t->tlv_detect == TAG_NDEF_TLV)  )
1155                {
1156                    tlv_value[2 - bytes_count] = p_readbytes[offset];
1157                    if (bytes_count == 0)
1158                    {
1159                        if (p_t1t->num_mem_tlvs >= RW_T1T_MAX_MEM_TLVS)
1160                        {
1161                            RW_TRACE_ERROR0 ("rw_t1t_handle_tlv_detect_rsp - Maximum buffer allocated for Memory tlv has reached");
1162                            failed  = TRUE;
1163                        }
1164                        else
1165                        {
1166                            /* Extract dynamic reserved bytes */
1167                            p_t1t->mem_tlv[p_t1t->num_mem_tlvs].offset   = (tlv_value[0] >> 4) & 0x0F;
1168                            p_t1t->mem_tlv[p_t1t->num_mem_tlvs].offset  *= (UINT8) tags_pow (2, tlv_value[2] & 0x0F);
1169                            p_t1t->mem_tlv[p_t1t->num_mem_tlvs].offset  += tlv_value[0] & 0x0F;
1170                            p_t1t->mem_tlv[p_t1t->num_mem_tlvs].num_bytes = tlv_value[1];
1171                            p_t1t->num_mem_tlvs++;
1172                            rw_t1t_update_attributes ();
1173                            tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
1174                        }
1175                    }
1176                }
1177                else
1178                {
1179                    if (bytes_count == 0)
1180                    {
1181                        tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
1182                    }
1183                }
1184                break;
1185
1186            case TAG_PROPRIETARY_TLV:
1187                bytes_count--;
1188                if (p_t1t->tlv_detect == TAG_PROPRIETARY_TLV)
1189                    found = TRUE;
1190                else
1191                {
1192                    if (bytes_count == 0)
1193                    {
1194                        tlv_detect_state = RW_T1T_SUBSTATE_WAIT_TLV_DETECT;
1195                    }
1196                }
1197                break;
1198            }
1199            offset++;
1200            break;
1201        }
1202    }
1203
1204    p_t1t->work_offset += bytes_read;
1205
1206    /* NDEF/Lock/Mem TLV to be found in segment 0, if not assume detection failed */
1207    if (!found && !failed)
1208    {
1209        if (  ((p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV) && (p_t1t->num_lockbytes > 0))
1210            ||((p_t1t->tlv_detect == TAG_MEM_CTRL_TLV) && (p_t1t->num_mem_tlvs > 0))  )
1211        {
1212            found = TRUE;
1213        }
1214        else
1215        {
1216            if (p_t1t->tlv_detect == TAG_NDEF_TLV)
1217            {
1218                p_t1t->tag_attribute = RW_T1_TAG_ATTRB_INITIALIZED;
1219            }
1220            failed = TRUE;
1221        }
1222    }
1223
1224
1225    status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1226    return status;
1227}
1228
1229/*******************************************************************************
1230**
1231** Function         rw_t1t_handle_ndef_rall_rsp
1232**
1233** Description      Handle response to RALL command sent while reading an
1234**                  NDEF message
1235**
1236** Returns          NFC_STATUS_CONTINUE, if NDEF read operation is not complete
1237**                  NFC_STATUS_OK, if NDEF read is successfull
1238**                  NFC_STATUS_FAILED,if NDEF read failed
1239**
1240*******************************************************************************/
1241static tNFC_STATUS rw_t1t_handle_ndef_rall_rsp (void)
1242{
1243    tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
1244    tNFC_STATUS status  = NFC_STATUS_CONTINUE;
1245    UINT8       count;
1246    UINT8       adds;
1247
1248    count               = (UINT8) p_t1t->ndef_msg_offset;
1249    p_t1t->work_offset  = 0;
1250    p_t1t->segment      = 0;
1251
1252    while (count < T1T_STATIC_SIZE && p_t1t->work_offset < p_t1t->ndef_msg_len)
1253    {
1254        if (rw_t1t_is_lock_reserved_otp_byte (count) == FALSE)
1255        {
1256            p_t1t->p_ndef_buffer[p_t1t->work_offset] = p_t1t->mem[count];
1257            p_t1t->work_offset++;
1258        }
1259        count++;
1260    }
1261    if (p_t1t->work_offset != p_t1t->ndef_msg_len)
1262    {
1263        if ((p_t1t->hr[0] & 0x0F) != 1)
1264        {
1265            if (p_t1t->work_offset == 0)
1266                return NFC_STATUS_FAILED;
1267
1268            else
1269            {
1270                p_t1t->block_read   = T1T_STATIC_BLOCKS + 1;
1271                p_t1t->segment++;
1272            }
1273            if (p_t1t->ndef_msg_len - p_t1t->work_offset <= 8)
1274            {
1275                if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_READ8, p_t1t->block_read, NULL)) == NFC_STATUS_OK)
1276                {
1277                    p_t1t->tlv_detect  = TAG_NDEF_TLV;
1278                    p_t1t->state    = RW_T1T_STATE_READ_NDEF;
1279                    status          = NFC_STATUS_CONTINUE;
1280                }
1281            }
1282            else
1283            {
1284                /* send RSEG command */
1285                RW_T1T_BLD_ADDS ((adds), (p_t1t->segment));
1286                if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_RSEG, adds, NULL)) == NFC_STATUS_OK)
1287                {
1288                    p_t1t->state    = RW_T1T_STATE_READ_NDEF;
1289                    status          = NFC_STATUS_CONTINUE;
1290                }
1291            }
1292        }
1293        else
1294        {
1295            RW_TRACE_ERROR1 ("RW_T1tReadNDef - Invalid NDEF len: %u or NDEF corrupted", p_t1t->ndef_msg_len);
1296            status = NFC_STATUS_FAILED;
1297        }
1298    }
1299    else
1300    {
1301        status = NFC_STATUS_OK;
1302    }
1303    return status;
1304}
1305
1306/*******************************************************************************
1307**
1308** Function         rw_t1t_handle_ndef_read_rsp
1309**
1310** Description      Handle response to commands sent while reading an
1311**                  NDEF message
1312**
1313** Returns          NFC_STATUS_CONTINUE, if tlv read is not yet complete
1314**                  NFC_STATUS_OK, if tlv read is complete & success
1315**                  NFC_STATUS_FAILED,if tlv read failed
1316**
1317*******************************************************************************/
1318static tNFC_STATUS rw_t1t_handle_ndef_read_rsp (UINT8 *p_data)
1319{
1320    tNFC_STATUS         ndef_status = NFC_STATUS_CONTINUE;
1321    tRW_T1T_CB          *p_t1t      = &rw_cb.tcb.t1t;
1322    UINT8               index;
1323    UINT8               adds;
1324    tT1T_CMD_RSP_INFO   *p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) rw_cb.tcb.t1t.p_cmd_rsp_info;
1325
1326    /* The Response received could be for Read8 or Read Segment command */
1327    switch(p_cmd_rsp_info->opcode)
1328    {
1329    case T1T_CMD_READ8:
1330        if (p_t1t->work_offset == 0)
1331        {
1332            index = p_t1t->ndef_msg_offset % T1T_BLOCK_SIZE;
1333        }
1334        else
1335        {
1336            index = 0;
1337        }
1338        p_t1t->segment = (p_t1t->block_read * T1T_BLOCK_SIZE)/T1T_SEGMENT_SIZE;
1339        while (index < T1T_BLOCK_SIZE && p_t1t->work_offset < p_t1t->ndef_msg_len)
1340        {
1341            if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) ((p_t1t->block_read * T1T_BLOCK_SIZE) + index)) == FALSE)
1342            {
1343                p_t1t->p_ndef_buffer[p_t1t->work_offset] = p_data[index];
1344                p_t1t->work_offset++;
1345            }
1346            index++;
1347        }
1348        break;
1349
1350    case T1T_CMD_RSEG:
1351        if (p_t1t->work_offset == 0)
1352        {
1353            index = p_t1t->ndef_msg_offset % T1T_SEGMENT_SIZE;
1354        }
1355        else
1356        {
1357            index = 0;
1358        }
1359        p_t1t->block_read = ((p_t1t->segment + 1) * T1T_BLOCKS_PER_SEGMENT) - 1;
1360
1361        while (index < T1T_SEGMENT_SIZE && p_t1t->work_offset < p_t1t->ndef_msg_len)
1362        {
1363            if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) (index)) == FALSE)
1364            {
1365                p_t1t->p_ndef_buffer[p_t1t->work_offset] = p_data[index];
1366                p_t1t->work_offset++;
1367            }
1368            index++;
1369        }
1370        break;
1371
1372    default:
1373        break;
1374    }
1375    if (p_t1t->work_offset < p_t1t->ndef_msg_len)
1376    {
1377        if ((p_t1t->hr[0] & 0x0F) != 1)
1378        {
1379            if ((p_t1t->ndef_msg_len - p_t1t->work_offset) <= T1T_BLOCK_SIZE)
1380            {
1381                p_t1t->block_read++;
1382                if ((ndef_status = rw_t1t_send_dyn_cmd (T1T_CMD_READ8, (UINT8) (p_t1t->block_read), NULL)) == NFC_STATUS_OK)
1383                {
1384                    ndef_status  = NFC_STATUS_CONTINUE;
1385                }
1386            }
1387            else
1388            {
1389                p_t1t->segment++;
1390                /* send RSEG command */
1391                RW_T1T_BLD_ADDS ((adds), (p_t1t->segment));
1392                if ((ndef_status = rw_t1t_send_dyn_cmd (T1T_CMD_RSEG, adds, NULL)) == NFC_STATUS_OK)
1393                {
1394                    ndef_status  = NFC_STATUS_CONTINUE;
1395                }
1396            }
1397        }
1398    }
1399    else
1400    {
1401        ndef_status = NFC_STATUS_OK;
1402    }
1403    return ndef_status;
1404}
1405
1406/*******************************************************************************
1407**
1408** Function         rw_t1t_next_ndef_write_block
1409**
1410** Description      This function prepare and writes ndef blocks
1411**
1412** Returns          NFC_STATUS_CONTINUE, if tlv write is not yet complete
1413**                  NFC_STATUS_OK, if tlv write is complete & success
1414**                  NFC_STATUS_FAILED,if tlv write failed
1415**
1416*******************************************************************************/
1417static tNFC_STATUS rw_t1t_next_ndef_write_block (void)
1418{
1419    BOOLEAN     b_block_write_cmd   = FALSE;
1420    tRW_T1T_CB  *p_t1t              = &rw_cb.tcb.t1t;
1421    tNFC_STATUS ndef_status         = NFC_STATUS_CONTINUE;
1422    UINT8       write_block[8];
1423    UINT8       block;
1424    UINT8       index;
1425    UINT8       new_lengthfield_len;
1426    UINT8       length_field[3];
1427    UINT16      initial_offset;
1428    UINT8       count;
1429    /* Write NDEF Message */
1430    new_lengthfield_len = p_t1t->new_ndef_msg_len > 254 ? 3:1;
1431
1432    /* Identify the command to use for NDEF write operation */
1433    if ((p_t1t->hr[0] & 0x0F) != 1)
1434    {
1435        /* Dynamic memory structure */
1436        b_block_write_cmd = FALSE;
1437        block           = p_t1t->ndef_block_written + 1;
1438        p_t1t->segment  = (block * T1T_BLOCK_SIZE) /T1T_SEGMENT_SIZE;
1439
1440        count = 0;
1441        while (block <= p_t1t->mem[T1T_CC_TMS_BYTE])
1442        {
1443            index = 0;
1444            if (block == p_t1t->num_ndef_finalblock)
1445            {
1446                /* T1T_CMD_WRITE_E8 Command */
1447                b_block_write_cmd = TRUE;
1448                break;
1449            }
1450            while (index < T1T_BLOCK_SIZE && p_t1t->work_offset < (p_t1t->new_ndef_msg_len + new_lengthfield_len))
1451            {
1452                if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) ((block * T1T_BLOCK_SIZE) + index)) == FALSE)
1453                {
1454                    count++;
1455                }
1456                index++;
1457            }
1458            if (count == T1T_BLOCK_SIZE)
1459            {
1460                /* T1T_CMD_WRITE_E8 Command */
1461                b_block_write_cmd = TRUE;
1462                break;
1463            }
1464            else if (count == 0)
1465            {
1466                index = 0;
1467                block++;
1468                if (p_t1t->segment != (block * T1T_BLOCK_SIZE) /T1T_SEGMENT_SIZE)
1469                {
1470                    p_t1t->segment = (block * T1T_BLOCK_SIZE) /T1T_SEGMENT_SIZE;
1471                }
1472            }
1473            else
1474            {
1475                /* T1T_CMD_WRITE_E Command */
1476                b_block_write_cmd = FALSE;
1477                break;
1478            }
1479        }
1480    }
1481    else
1482    {
1483        /* Static memory structure */
1484        block       = p_t1t->ndef_block_written;
1485        b_block_write_cmd = FALSE;
1486    }
1487
1488    new_lengthfield_len = p_t1t->new_ndef_msg_len > 254 ? 3:1;
1489    if (new_lengthfield_len == 3)
1490    {
1491        length_field[0] = T1T_LONG_NDEF_LEN_FIELD_BYTE0;
1492        length_field[1] = (UINT8) (p_t1t->new_ndef_msg_len >> 8);
1493        length_field[2] = (UINT8) (p_t1t->new_ndef_msg_len);
1494    }
1495    else
1496    {
1497        length_field[0] = (UINT8) (p_t1t->new_ndef_msg_len);
1498    }
1499
1500    if (b_block_write_cmd)
1501    {
1502        /* Dynamic memory structure */
1503        index           = 0;
1504        p_t1t->segment  = (block * T1T_BLOCK_SIZE) /T1T_SEGMENT_SIZE;
1505
1506        initial_offset  = p_t1t->work_offset;
1507        block = rw_t1t_prepare_ndef_bytes (write_block, length_field,  &index, FALSE, block, new_lengthfield_len);
1508        if (p_t1t->work_offset == initial_offset)
1509        {
1510            ndef_status = NFC_STATUS_FAILED;
1511        }
1512        else
1513        {
1514            /* Send WRITE_E8 command */
1515            ndef_status = rw_t1t_send_ndef_block (write_block, block);
1516        }
1517    }
1518    else
1519    {
1520        /* Static memory structure */
1521        if (p_t1t->write_byte + 1 >= T1T_BLOCK_SIZE)
1522        {
1523            index = 0;
1524            block++;
1525        }
1526        else
1527        {
1528            index       = p_t1t->write_byte + 1;
1529        }
1530        initial_offset  = p_t1t->work_offset;
1531        block = rw_t1t_prepare_ndef_bytes (write_block, length_field, &index, TRUE, block, new_lengthfield_len);
1532        if (p_t1t->work_offset == initial_offset)
1533        {
1534            ndef_status = NFC_STATUS_FAILED;
1535        }
1536        else
1537        {
1538            /* send WRITE-E command */
1539            ndef_status = rw_t1t_send_ndef_byte (write_block[index], block, index, new_lengthfield_len);
1540        }
1541    }
1542    return ndef_status;
1543
1544}
1545
1546/*******************************************************************************
1547**
1548** Function         rw_t1t_ndef_write_first_block
1549**
1550** Description      This function writes ndef first block
1551**
1552** Returns          NFC_STATUS_CONTINUE, if tlv write is not yet complete
1553**                  NFC_STATUS_OK, if tlv write is complete & success
1554**                  NFC_STATUS_FAILED,if tlv write failed
1555**
1556*******************************************************************************/
1557static tNFC_STATUS rw_t1t_ndef_write_first_block (void)
1558{
1559    tNFC_STATUS ndef_status = NFC_STATUS_CONTINUE;
1560    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
1561    UINT8       block;
1562    UINT8       index;
1563    UINT8       new_lengthfield_len;
1564    UINT8       length_field[3];
1565    UINT8       write_block[8];
1566
1567    /* handle positive response to invalidating existing NDEF Message */
1568    p_t1t->work_offset = 0;
1569    new_lengthfield_len = p_t1t->new_ndef_msg_len > 254 ? 3:1;
1570    if (new_lengthfield_len == 3)
1571    {
1572        length_field[0] = T1T_LONG_NDEF_LEN_FIELD_BYTE0;
1573        length_field[1] = (UINT8) (p_t1t->new_ndef_msg_len >> 8);
1574        length_field[2] = (UINT8) (p_t1t->new_ndef_msg_len);
1575    }
1576    else
1577    {
1578        length_field[0] = (UINT8) (p_t1t->new_ndef_msg_len);
1579    }
1580    /* updating ndef_first_block with new ndef message */
1581    memcpy(write_block,p_t1t->ndef_first_block,T1T_BLOCK_SIZE);
1582    index = p_t1t->ndef_header_offset % T1T_BLOCK_SIZE;
1583    block = (UINT8) (p_t1t->ndef_header_offset / T1T_BLOCK_SIZE);
1584    p_t1t->segment      = (UINT8) (p_t1t->ndef_header_offset/T1T_SEGMENT_SIZE);
1585
1586    if ((p_t1t->hr[0] & 0x0F) != 1)
1587    {
1588        /* Dynamic Memory structure */
1589        block = rw_t1t_prepare_ndef_bytes (write_block, length_field, &index, FALSE, block, new_lengthfield_len);
1590
1591        if (p_t1t->work_offset == 0)
1592        {
1593            ndef_status = NFC_STATUS_FAILED;
1594        }
1595        else
1596        {
1597            /* Send WRITE-E8 command based on the prepared write_block */
1598            ndef_status = rw_t1t_send_ndef_block (write_block, block);
1599        }
1600    }
1601    else
1602    {
1603        /* Static Memory structure */
1604        block = rw_t1t_prepare_ndef_bytes (write_block, length_field, &index, TRUE, block, new_lengthfield_len);
1605        if (p_t1t->work_offset == 0)
1606        {
1607            ndef_status = NFC_STATUS_FAILED;
1608        }
1609        else
1610        {
1611            /* send WRITE-E command */
1612            ndef_status = rw_t1t_send_ndef_byte (write_block[index], block, index, new_lengthfield_len);
1613        }
1614    }
1615
1616    return ndef_status;
1617}
1618
1619/*******************************************************************************
1620**
1621** Function         rw_t1t_send_ndef_byte
1622**
1623** Description      Sends ndef message or length field byte and update
1624**                  status
1625**
1626** Returns          NFC_STATUS_CONTINUE, if tlv write is not yet complete
1627**                  NFC_STATUS_OK, if tlv write is complete & success
1628**                  NFC_STATUS_FAILED,if tlv write failed
1629**
1630*******************************************************************************/
1631static tNFC_STATUS rw_t1t_send_ndef_byte (UINT8 data, UINT8 block, UINT8 index, UINT8 msg_len)
1632{
1633    tNFC_STATUS ndef_status = NFC_STATUS_CONTINUE;
1634    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
1635    UINT8       addr;
1636
1637    /* send WRITE-E command */
1638    RW_T1T_BLD_ADD ((addr), (block), (index));
1639    if (NFC_STATUS_OK == rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, data))
1640    {
1641        p_t1t->write_byte           = index;
1642        p_t1t->ndef_block_written   = block;
1643        if (p_t1t->work_offset == p_t1t->new_ndef_msg_len + msg_len)
1644        {
1645            ndef_status =  NFC_STATUS_OK;
1646        }
1647        else
1648        {
1649            ndef_status = NFC_STATUS_CONTINUE;
1650        }
1651    }
1652    else
1653    {
1654        ndef_status = NFC_STATUS_FAILED;
1655    }
1656    return ndef_status;
1657}
1658
1659/*******************************************************************************
1660**
1661** Function         rw_t1t_prepare_ndef_bytes
1662**
1663** Description      prepares ndef block to write
1664**
1665** Returns          block number where to write
1666**
1667*******************************************************************************/
1668static UINT8 rw_t1t_prepare_ndef_bytes (UINT8 *p_data, UINT8 *p_length_field, UINT8 *p_index, BOOLEAN b_one_byte, UINT8 block, UINT8 lengthfield_len)
1669{
1670    tRW_T1T_CB  *p_t1t          = &rw_cb.tcb.t1t;
1671    UINT8       first_block     = (UINT8) (p_t1t->ndef_header_offset / T1T_BLOCK_SIZE);
1672    UINT16      initial_offset  = p_t1t->work_offset;
1673
1674    while (p_t1t->work_offset == initial_offset && block <= p_t1t->mem[T1T_CC_TMS_BYTE])
1675    {
1676        if (  (block == p_t1t->num_ndef_finalblock)
1677            &&(block != first_block)  )
1678        {
1679            memcpy (p_data,p_t1t->ndef_final_block,T1T_BLOCK_SIZE);
1680        }
1681        /* Update length field */
1682        while (  (*p_index < T1T_BLOCK_SIZE)
1683               &&(p_t1t->work_offset < lengthfield_len)  )
1684        {
1685            if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) ((block * T1T_BLOCK_SIZE) + *p_index)) == FALSE)
1686            {
1687                p_data[*p_index] = p_length_field[p_t1t->work_offset];
1688                p_t1t->work_offset++;
1689                if (b_one_byte)
1690                    return block;
1691            }
1692            (*p_index)++;
1693            if (p_t1t->work_offset == lengthfield_len)
1694            {
1695                break;
1696            }
1697        }
1698        /* Update ndef message field */
1699        while (*p_index < T1T_BLOCK_SIZE && p_t1t->work_offset < (p_t1t->new_ndef_msg_len + lengthfield_len))
1700        {
1701            if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) ((block * T1T_BLOCK_SIZE) + *p_index)) == FALSE)
1702            {
1703                p_data[*p_index] = p_t1t->p_ndef_buffer[p_t1t->work_offset - lengthfield_len];
1704                p_t1t->work_offset++;
1705                if (b_one_byte)
1706                    return block;
1707            }
1708            (*p_index)++;
1709        }
1710        if (p_t1t->work_offset == initial_offset)
1711        {
1712            *p_index = 0;
1713            block++;
1714            if (p_t1t->segment != (block * T1T_BLOCK_SIZE) /T1T_SEGMENT_SIZE)
1715            {
1716                p_t1t->segment = (block * T1T_BLOCK_SIZE) /T1T_SEGMENT_SIZE;
1717            }
1718        }
1719    }
1720    return block;
1721}
1722
1723/*******************************************************************************
1724**
1725** Function         rw_t1t_send_ndef_block
1726**
1727** Description      Sends ndef block and update status
1728**
1729** Returns          NFC_STATUS_CONTINUE, if tlv write is not yet complete
1730**                  NFC_STATUS_OK, if tlv write is complete & success
1731**                  NFC_STATUS_FAILED,if tlv write failed
1732**
1733*******************************************************************************/
1734static tNFC_STATUS rw_t1t_send_ndef_block (UINT8 *p_data, UINT8 block)
1735{
1736    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
1737    tNFC_STATUS ndef_status = NFC_STATUS_CONTINUE;
1738
1739    if (NFC_STATUS_OK == rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_E8, block, p_data))
1740    {
1741        p_t1t->ndef_block_written = block;
1742        if (p_t1t->ndef_block_written == p_t1t->num_ndef_finalblock)
1743        {
1744            ndef_status  =  NFC_STATUS_OK;
1745        }
1746        else
1747        {
1748             ndef_status =  NFC_STATUS_CONTINUE;
1749        }
1750    }
1751    else
1752    {
1753        ndef_status = NFC_STATUS_FAILED;
1754    }
1755    return ndef_status;
1756}
1757
1758/*******************************************************************************
1759**
1760** Function         rw_t1t_get_ndef_flags
1761**
1762** Description      Prepare NDEF Flags
1763**
1764** Returns          NDEF Flag value
1765**
1766*******************************************************************************/
1767static UINT8 rw_t1t_get_ndef_flags (void)
1768{
1769    UINT8       flags   = 0;
1770    tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
1771
1772    if ((p_t1t->hr[0] & 0xF0) == T1T_NDEF_SUPPORTED)
1773        flags |= RW_NDEF_FL_SUPPORTED;
1774
1775    if (t1t_tag_init_data (p_t1t->hr[0]) != NULL)
1776        flags |= RW_NDEF_FL_FORMATABLE;
1777
1778    if ((p_t1t->mem[T1T_CC_RWA_BYTE] & 0x0F) == T1T_CC_RWA_RO)
1779        flags |=RW_NDEF_FL_READ_ONLY;
1780
1781    return flags;
1782}
1783
1784/*******************************************************************************
1785**
1786** Function         rw_t1t_get_ndef_max_size
1787**
1788** Description      Calculate maximum size of NDEF message that can be written
1789**                  on to the tag
1790**
1791** Returns          Maximum size of NDEF Message
1792**
1793*******************************************************************************/
1794static UINT16 rw_t1t_get_ndef_max_size (void)
1795{
1796    UINT16              offset;
1797    tRW_T1T_CB          *p_t1t   = &rw_cb.tcb.t1t;
1798    UINT16              tag_size = (p_t1t->mem[T1T_CC_TMS_BYTE] +1)* T1T_BLOCK_SIZE;
1799    const tT1T_INIT_TAG *p_ret;
1800    UINT8               init_segment = p_t1t->segment;
1801
1802    p_t1t->max_ndef_msg_len = 0;
1803    offset                  = p_t1t->ndef_msg_offset;
1804    p_t1t->segment          = (UINT8) (p_t1t->ndef_msg_offset/T1T_SEGMENT_SIZE);
1805
1806    if (  (tag_size < T1T_STATIC_SIZE)
1807        ||(tag_size > (T1T_SEGMENT_SIZE * T1T_MAX_SEGMENTS))
1808        ||((p_t1t->mem[T1T_CC_NMN_BYTE] != T1T_CC_NMN) && (p_t1t->mem[T1T_CC_NMN_BYTE] != 0))  )
1809    {
1810        /* Tag not formated, determine maximum NDEF size from HR */
1811        if  (  ((p_t1t->hr[0] & 0xF0) == T1T_NDEF_SUPPORTED)
1812             &&((p_ret = t1t_tag_init_data (p_t1t->hr[0])) != NULL)  )
1813        {
1814            p_t1t->max_ndef_msg_len = ((p_ret->tms +1)* T1T_BLOCK_SIZE) - T1T_OTP_LOCK_RES_BYTES - T1T_UID_LEN - T1T_ADD_LEN - T1T_CC_LEN - T1T_TLV_TYPE_LEN - T1T_SHORT_NDEF_LEN_FIELD_LEN;
1815            if (p_ret->b_dynamic)
1816            {
1817                p_t1t->max_ndef_msg_len -= (T1T_TLV_TYPE_LEN + T1T_DEFAULT_TLV_LEN_FIELD_LEN + T1T_DEFAULT_TLV_LEN + T1T_TLV_TYPE_LEN + T1T_DEFAULT_TLV_LEN_FIELD_LEN + T1T_DEFAULT_TLV_LEN);
1818                p_t1t->max_ndef_msg_len -= T1T_DYNAMIC_LOCK_BYTES;
1819            }
1820            offset = tag_size;
1821        }
1822        else
1823        {
1824            p_t1t->segment = init_segment;
1825            return p_t1t->max_ndef_msg_len;
1826        }
1827    }
1828
1829    /* Starting from NDEF Message offset find the first locked data byte */
1830    while (offset < tag_size)
1831    {
1832        if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) (offset)) == FALSE)
1833        {
1834            if (rw_t1t_is_read_only_byte ((UINT16) offset) == TRUE)
1835                break;
1836            p_t1t->max_ndef_msg_len++;
1837        }
1838        offset++;
1839        if (offset % T1T_SEGMENT_SIZE == 0)
1840        {
1841            p_t1t->segment = (UINT8) (offset / T1T_SEGMENT_SIZE);
1842        }
1843    }
1844    /* NDEF Length field length changes based on NDEF size */
1845    if (  (p_t1t->max_ndef_msg_len >= T1T_LONG_NDEF_LEN_FIELD_BYTE0)
1846        &&((p_t1t->ndef_msg_offset - p_t1t->ndef_header_offset) == T1T_SHORT_NDEF_LEN_FIELD_LEN)  )
1847    {
1848        p_t1t->max_ndef_msg_len -=  (p_t1t->max_ndef_msg_len == T1T_LONG_NDEF_LEN_FIELD_BYTE0)? 1 : (T1T_LONG_NDEF_LEN_FIELD_LEN - T1T_SHORT_NDEF_LEN_FIELD_LEN);
1849    }
1850
1851    p_t1t->segment = init_segment;
1852    return p_t1t->max_ndef_msg_len;
1853}
1854
1855/*******************************************************************************
1856**
1857** Function         rw_t1t_handle_ndef_write_rsp
1858**
1859** Description      Handle response to commands sent while writing an
1860**                  NDEF message
1861**
1862** Returns          NFC_STATUS_CONTINUE, if tlv write is not yet complete
1863**                  NFC_STATUS_OK, if tlv write is complete & success
1864**                  NFC_STATUS_FAILED,if tlv write failed
1865**
1866*******************************************************************************/
1867static tNFC_STATUS rw_t1t_handle_ndef_write_rsp (UINT8 *p_data)
1868{
1869    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
1870    tNFC_STATUS ndef_status = NFC_STATUS_CONTINUE;
1871    UINT8       addr;
1872
1873    switch (p_t1t->substate)
1874    {
1875    case RW_T1T_SUBSTATE_WAIT_READ_NDEF_BLOCK:
1876        /* Backup ndef_final_block */
1877        memcpy (p_t1t->ndef_final_block, p_data, T1T_BLOCK_SIZE);
1878        /* Invalidate existing NDEF Message */
1879        RW_T1T_BLD_ADD ((addr), (T1T_CC_BLOCK), (T1T_CC_NMN_OFFSET));
1880        if (NFC_STATUS_OK == rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, 0))
1881        {
1882            ndef_status     = NFC_STATUS_CONTINUE;
1883            p_t1t->state    = RW_T1T_STATE_WRITE_NDEF;
1884            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_INVALIDATE_NDEF;
1885        }
1886        else
1887        {
1888            ndef_status = NFC_STATUS_FAILED;
1889        }
1890        break;
1891
1892    case RW_T1T_SUBSTATE_WAIT_INVALIDATE_NDEF:
1893        ndef_status = rw_t1t_ndef_write_first_block ();
1894        break;
1895
1896    case RW_T1T_SUBSTATE_WAIT_NDEF_WRITE:
1897        ndef_status = rw_t1t_next_ndef_write_block ();
1898        break;
1899
1900    case RW_T1T_SUBSTATE_WAIT_NDEF_UPDATED:
1901        /* Validate new NDEF Message */
1902        RW_T1T_BLD_ADD ((addr), (T1T_CC_BLOCK), (T1T_CC_NMN_OFFSET));
1903        if (NFC_STATUS_OK == rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, T1T_CC_NMN))
1904        {
1905            ndef_status     = NFC_STATUS_OK;
1906        }
1907        else
1908        {
1909            ndef_status     = NFC_STATUS_FAILED;
1910        }
1911        break;
1912    default:
1913        break;
1914    }
1915
1916    return ndef_status;
1917}
1918
1919/*******************************************************************************
1920**
1921** Function         rw_t1t_update_attributes
1922**
1923** Description      This function will prepare attributes for the current
1924**                  segment. Every bit in the attribute refers to one byte of
1925**                  tag content.The bit corresponding to a tag byte will be set
1926**                  to '1' when the Tag byte is read only,otherwise will be set
1927**                  to '0'
1928**
1929** Returns          None
1930**
1931*******************************************************************************/
1932static void rw_t1t_update_attributes (void)
1933{
1934    UINT8       count       = 0;
1935    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
1936    UINT16      lower_offset;
1937    UINT16      upper_offset;
1938    UINT8       num_bytes;
1939    UINT16      offset;
1940    UINT8       bits_per_byte  = 8;
1941
1942    count = 0;
1943    while (count < T1T_BLOCKS_PER_SEGMENT)
1944    {
1945        p_t1t->attr[count] = 0x00;
1946        count++;
1947    }
1948
1949    lower_offset  = p_t1t->segment * T1T_SEGMENT_SIZE;
1950    upper_offset  = (p_t1t->segment + 1)* T1T_SEGMENT_SIZE;
1951
1952    if (p_t1t->segment == 0)
1953    {
1954        /* UID/Lock/Reserved/OTP bytes */
1955        p_t1t->attr[0x00] = 0xFF; /* Uid bytes */
1956        p_t1t->attr[0x0D] = 0xFF; /* Reserved bytes */
1957        p_t1t->attr[0x0E] = 0xFF; /* lock/otp bytes */
1958        p_t1t->attr[0x0F] = 0xFF; /* lock/otp bytes */
1959    }
1960
1961    /* update attr based on lock control and mem control tlvs */
1962    count = 0;
1963    while (count < p_t1t->num_lockbytes)
1964    {
1965        offset = p_t1t->lock_tlv[p_t1t->lockbyte[count].tlv_index].offset + p_t1t->lockbyte[count].byte_index;
1966        if (offset >= lower_offset && offset < upper_offset)
1967        {
1968            /* Set the corresponding bit in attr to indicate - lock byte */
1969            p_t1t->attr[(offset % T1T_SEGMENT_SIZE) / bits_per_byte] |= rw_t1t_mask_bits[(offset % T1T_SEGMENT_SIZE) % bits_per_byte];
1970        }
1971        count++;
1972    }
1973    count = 0;
1974    while (count < p_t1t->num_mem_tlvs)
1975    {
1976        num_bytes = 0;
1977        while (num_bytes < p_t1t->mem_tlv[count].num_bytes)
1978        {
1979            offset = p_t1t->mem_tlv[count].offset + num_bytes;
1980            if (offset >= lower_offset && offset < upper_offset)
1981            {
1982                /* Set the corresponding bit in attr to indicate - reserved byte */
1983                p_t1t->attr[(offset % T1T_SEGMENT_SIZE) / bits_per_byte] |= rw_t1t_mask_bits[(offset % T1T_SEGMENT_SIZE) % bits_per_byte];
1984            }
1985            num_bytes++;
1986        }
1987        count++;
1988    }
1989}
1990
1991/*******************************************************************************
1992**
1993** Function         rw_t1t_get_lock_bits_for_segment
1994**
1995** Description      This function will identify the index of the dynamic lock
1996**                  byte that covers the current segment
1997**
1998** Parameters:      segment, segment number
1999**                  p_start_byte, pointer to hold the first lock byte index
2000**                  p_start_bit, pointer to hold the first lock bit index
2001**                  p_end_byte, pointer to hold the last lock byte index
2002**
2003** Returns          Total lock bits that covers the specified segment
2004**
2005*******************************************************************************/
2006static UINT8 rw_t1t_get_lock_bits_for_segment (UINT8 segment,UINT8 *p_start_byte, UINT8 *p_start_bit,UINT8 *p_end_byte)
2007{
2008    tRW_T1T_CB  *p_t1t              = &rw_cb.tcb.t1t;
2009    UINT16      byte_count          = T1T_SEGMENT_SIZE;
2010    UINT8       total_bits          = 0;
2011    UINT8       num_dynamic_locks   = 0;
2012    UINT8       bit_count           = 0;
2013    UINT16      tag_size            = (p_t1t->mem[T1T_CC_TMS_BYTE] +1) * T1T_BLOCK_SIZE;
2014    UINT16      lower_offset;
2015    UINT16      upper_offset;
2016    BOOLEAN     b_all_bits_are_locks = TRUE;
2017    UINT8       bytes_locked_per_bit;
2018    UINT8       num_bits;
2019
2020    upper_offset    = (segment + 1) * T1T_SEGMENT_SIZE;
2021
2022    if (upper_offset > tag_size)
2023        upper_offset = tag_size;
2024
2025    lower_offset    = segment * T1T_SEGMENT_SIZE;
2026    *p_start_byte   = num_dynamic_locks;
2027    *p_start_bit    = 0;
2028
2029    while (  (byte_count <= lower_offset)
2030           &&(num_dynamic_locks < p_t1t->num_lockbytes)  )
2031    {
2032        bytes_locked_per_bit = p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_locks].tlv_index].bytes_locked_per_bit;
2033        /* Number of bits in the current lock byte */
2034        b_all_bits_are_locks = ((p_t1t->lockbyte[num_dynamic_locks].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_locks].tlv_index].num_bits);
2035        num_bits = b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_locks].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2036
2037        /* Skip lock bits that covers all previous segments */
2038        if (bytes_locked_per_bit * num_bits + byte_count <= lower_offset)
2039        {
2040            byte_count += bytes_locked_per_bit * num_bits;
2041            num_dynamic_locks++;
2042        }
2043        else
2044        {
2045            /* The first lock bit that covers this segment is present in this segment */
2046            bit_count = 0;
2047            while (bit_count < num_bits)
2048            {
2049                byte_count += bytes_locked_per_bit;
2050                if (byte_count > lower_offset)
2051                {
2052                    *p_start_byte = num_dynamic_locks;
2053                    *p_end_byte = num_dynamic_locks;
2054                    *p_start_bit  = bit_count;
2055                    bit_count++;
2056                    total_bits = 1;
2057                    break;
2058                }
2059                bit_count++;
2060            }
2061        }
2062    }
2063    if (num_dynamic_locks == p_t1t->num_lockbytes)
2064    {
2065        return 0;
2066    }
2067    while (  (byte_count < upper_offset)
2068           &&(num_dynamic_locks < p_t1t->num_lockbytes)  )
2069    {
2070        bytes_locked_per_bit = p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_locks].tlv_index].bytes_locked_per_bit;
2071
2072        /* Number of bits in the current lock byte */
2073        b_all_bits_are_locks = ((p_t1t->lockbyte[num_dynamic_locks].byte_index + 1) * TAG_BITS_PER_BYTE <= p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_locks].tlv_index].num_bits);
2074        num_bits             =  b_all_bits_are_locks ? TAG_BITS_PER_BYTE : p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_locks].tlv_index].num_bits % TAG_BITS_PER_BYTE;
2075
2076        /* Collect all lock bits that covers the current segment */
2077        if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count < upper_offset)
2078        {
2079            byte_count       += bytes_locked_per_bit * (num_bits - bit_count);
2080            total_bits       += num_bits - bit_count;
2081            bit_count         = 0;
2082            *p_end_byte       = num_dynamic_locks;
2083            num_dynamic_locks++;
2084        }
2085        else
2086        {
2087            /* The last lock byte that covers the current segment */
2088            bit_count = 0;
2089            while (bit_count < num_bits)
2090            {
2091                byte_count += bytes_locked_per_bit;
2092                if (byte_count >= upper_offset)
2093                {
2094                    *p_end_byte = num_dynamic_locks;
2095                    total_bits += (bit_count + 1);
2096                    break;
2097                }
2098                bit_count++;
2099            }
2100        }
2101    }
2102    return total_bits;
2103}
2104
2105/*******************************************************************************
2106**
2107** Function         rw_t1t_update_lock_attributes
2108**
2109** Description      This function will check if the tag index passed as
2110**                  argument is a locked byte and return
2111**                  TRUE or FALSE
2112**
2113** Parameters:      index, the index of the byte in the tag
2114**
2115**
2116** Returns          TRUE, if the specified index in the tag is a locked or
2117**                        reserved or otp byte
2118**                  FALSE, otherwise
2119**
2120*******************************************************************************/
2121static void rw_t1t_update_lock_attributes (void)
2122{
2123    UINT8       xx = 0;
2124    UINT8       bytes_locked_per_lock_bit;
2125    UINT8       num_static_lock_bytes       = 0;
2126    UINT8       num_dynamic_lock_bytes      = 0;
2127    UINT8       bits_covered                = 0;
2128    UINT8       bytes_covered               = 0;
2129    UINT8       block_count                 = 0;
2130    tRW_T1T_CB  *p_t1t = &rw_cb.tcb.t1t;
2131    UINT8       start_lock_byte;
2132    UINT8       start_lock_bit;
2133    UINT8       end_lock_byte;
2134    UINT8       num_lock_bits;
2135    UINT8       total_bits;
2136
2137
2138    block_count = 0;
2139    while (block_count < T1T_BLOCKS_PER_SEGMENT)
2140    {
2141        p_t1t->lock_attr[block_count] = 0x00;
2142        block_count++;
2143    }
2144
2145    /* update lock_attr based on static lock bytes */
2146    if (p_t1t->segment == 0)
2147    {
2148        xx                      = 0;
2149        num_static_lock_bytes   = 0;
2150        block_count             = 0;
2151        num_lock_bits           = 8;
2152
2153        while (num_static_lock_bytes < T1T_NUM_STATIC_LOCK_BYTES)
2154        {
2155            /* Update lock attribute based on 2 static locks */
2156            while (xx < num_lock_bits)
2157            {
2158                p_t1t->lock_attr[block_count] = 0x00;
2159
2160                if (p_t1t->mem[T1T_LOCK_0_OFFSET + num_static_lock_bytes] & rw_t1t_mask_bits[xx++])
2161                {
2162                    /* If the bit is set then 1 block is locked */
2163                    p_t1t->lock_attr[block_count] = 0xFF;
2164                }
2165
2166                block_count++;
2167            }
2168            num_static_lock_bytes++;
2169            xx = 0;
2170        }
2171        /* Locked bytes */
2172        p_t1t->lock_attr[0x00] = 0xFF;
2173        p_t1t->lock_attr[0x0D] = 0xFF;
2174    }
2175    else
2176    {
2177        /* update lock_attr based on segment and using dynamic lock bytes */
2178        if ((total_bits = rw_t1t_get_lock_bits_for_segment (p_t1t->segment,&start_lock_byte, &start_lock_bit,&end_lock_byte)) != 0)
2179        {
2180            xx                       = start_lock_bit;
2181            num_dynamic_lock_bytes   = start_lock_byte;
2182            bits_covered             = 0;
2183            bytes_covered            = 0;
2184            block_count              = 0;
2185            num_lock_bits            = 8;
2186
2187            p_t1t->lock_attr[block_count] = 0;
2188
2189            while (num_dynamic_lock_bytes <= end_lock_byte)
2190            {
2191                bytes_locked_per_lock_bit   = p_t1t->lock_tlv[p_t1t->lockbyte[num_dynamic_lock_bytes].tlv_index].bytes_locked_per_bit;
2192                if (num_dynamic_lock_bytes == end_lock_byte)
2193                {
2194                    num_lock_bits = (total_bits % 8 == 0)? 8:total_bits % 8;
2195                }
2196                while (xx < num_lock_bits)
2197                {
2198                    bytes_covered = 0;
2199                    while (bytes_covered < bytes_locked_per_lock_bit)
2200                    {
2201                        /* Set/clear lock_attr byte bits based on whether a particular lock bit is set or not
2202                         * each bit in lock_attr represents one byte in Tag read only attribute */
2203                        if (p_t1t->lockbyte[num_dynamic_lock_bytes].lock_byte & rw_t1t_mask_bits[xx])
2204                        {
2205                            p_t1t->lock_attr[block_count] |= 0x01 << bits_covered;
2206                        }
2207                        bytes_covered++;
2208                        bits_covered++;
2209                        if (bits_covered == 8)
2210                        {
2211                            bits_covered = 0;
2212                            block_count++;
2213                            if (block_count < T1T_BLOCKS_PER_SEGMENT)
2214                                p_t1t->lock_attr[block_count] = 0;
2215                        }
2216                    }
2217                    xx++;
2218                }
2219                num_dynamic_lock_bytes++;
2220                xx = 0;
2221            }
2222        }
2223    }
2224}
2225
2226/*******************************************************************************
2227**
2228** Function         rw_t1t_is_lock_reserved_otp_byte
2229**
2230** Description      This function will check if the tag index passed as
2231**                  argument is a lock or reserved or otp byte
2232**
2233** Parameters:      index, the index of the byte in the tag's current segment
2234**
2235**
2236** Returns          TRUE, if the specified index in the tag is a locked or
2237**                        reserved or otp byte
2238**                  FALSE, otherwise
2239**
2240*******************************************************************************/
2241static BOOLEAN rw_t1t_is_lock_reserved_otp_byte (UINT16 index)
2242{
2243    tRW_T1T_CB  *p_t1t = &rw_cb.tcb.t1t;
2244
2245    if (p_t1t->attr_seg != p_t1t->segment)
2246    {
2247        /* Update p_t1t->attr to reflect the current segment */
2248        rw_t1t_update_attributes ();
2249        p_t1t->attr_seg = p_t1t->segment;
2250    }
2251    index = index % T1T_SEGMENT_SIZE;
2252
2253    /* Every bit in p_t1t->attr indicates one specific byte of the tag is either a lock/reserved/otp byte or not
2254     * So, each array element in p_t1t->attr covers one block in the tag as T1 block size and array element size is 8
2255     * Find the block and offset for the index (passed as argument) and Check if the offset bit in the
2256     * p_t1t->attr[block] is set or not. If the bit is set then it is a lock/reserved/otp byte, otherwise not */
2257
2258    return ((p_t1t->attr[index /8] & rw_t1t_mask_bits[index % 8]) == 0) ? FALSE:TRUE;
2259}
2260
2261/*******************************************************************************
2262**
2263** Function         rw_t1t_is_read_only_byte
2264**
2265** Description      This function will check if the tag index passed as
2266**                  argument is a read only byte
2267**
2268** Parameters:      index, the index of the byte in the tag's current segment
2269**
2270**
2271** Returns          TRUE, if the specified index in the tag is a locked or
2272**                        reserved or otp byte
2273**                  FALSE, otherwise
2274**
2275*******************************************************************************/
2276static BOOLEAN rw_t1t_is_read_only_byte (UINT16 index)
2277{
2278    tRW_T1T_CB  *p_t1t = &rw_cb.tcb.t1t;
2279
2280    if (p_t1t->lock_attr_seg != p_t1t->segment)
2281    {
2282        /* Update p_t1t->lock_attr to reflect the current segment */
2283        rw_t1t_update_lock_attributes ();
2284        p_t1t->lock_attr_seg = p_t1t->segment;
2285    }
2286
2287    index = index % T1T_SEGMENT_SIZE;
2288    /* Every bit in p_t1t->lock_attr indicates one specific byte of the tag is a read only byte or read write byte
2289     * So, each array element in p_t1t->lock_attr covers one block in the tag as T1 block size and array element size is 8
2290     * Find the block and offset for the index (passed as argument) and Check if the offset bit in the
2291     * p_t1t->lock_attr[block] is set or not. If the bit is set then it is a read only byte, otherwise read write byte */
2292
2293    return ((p_t1t->lock_attr[index /8] & rw_t1t_mask_bits[index % 8]) == 0) ? FALSE:TRUE;
2294}
2295
2296/*****************************************************************************
2297**
2298** Function         RW_T1tFormatNDef
2299**
2300** Description
2301**      Format Tag content
2302**
2303** Returns
2304**      NFC_STATUS_OK, Command sent to format Tag
2305**      NFC_STATUS_REJECTED: Invalid HR0 and cannot format the tag
2306**      NFC_STATUS_FAILED: other error
2307**
2308*****************************************************************************/
2309tNFC_STATUS RW_T1tFormatNDef (void)
2310{
2311    tRW_T1T_CB          *p_t1t  = &rw_cb.tcb.t1t;
2312    tNFC_STATUS         status  = NFC_STATUS_FAILED;
2313    const tT1T_INIT_TAG *p_ret;
2314    UINT8               addr;
2315    UINT8               *p;
2316
2317    if (p_t1t->state != RW_T1T_STATE_IDLE)
2318    {
2319        RW_TRACE_WARNING1 ("RW_T1tFormatNDef - Tag not initialized/ Busy! State: %u", p_t1t->state);
2320        return (NFC_STATUS_FAILED);
2321    }
2322
2323    if ((p_t1t->hr[0] & 0xF0) != T1T_NDEF_SUPPORTED)
2324    {
2325        RW_TRACE_WARNING1 ("RW_T1tFormatNDef - Cannot format tag as NDEF not supported. HR0: %u", p_t1t->hr[0]);
2326        return (NFC_STATUS_REJECTED);
2327    }
2328
2329    if ((p_ret = t1t_tag_init_data (p_t1t->hr[0])) == NULL)
2330    {
2331        RW_TRACE_WARNING2 ("RW_T1tFormatNDef - Invalid HR - HR0: %u, HR1: %u", p_t1t->hr[0], p_t1t->hr[1]);
2332        return (NFC_STATUS_REJECTED);
2333    }
2334
2335    memset (p_t1t->ndef_first_block, 0, T1T_BLOCK_SIZE);
2336    memset (p_t1t->ndef_final_block, 0, T1T_BLOCK_SIZE);
2337    p = p_t1t->ndef_first_block;
2338
2339    /* Prepare Capability Container */
2340    UINT8_TO_BE_STREAM (p, T1T_CC_NMN);
2341    UINT8_TO_BE_STREAM (p, T1T_CC_VNO);
2342    UINT8_TO_BE_STREAM (p, p_ret->tms);
2343    UINT8_TO_BE_STREAM (p, T1T_CC_RWA_RW);
2344    if (p_ret->b_dynamic)
2345    {
2346        /* Prepare Lock and Memory TLV */
2347        UINT8_TO_BE_STREAM (p, TAG_LOCK_CTRL_TLV);
2348        UINT8_TO_BE_STREAM (p, T1T_DEFAULT_TLV_LEN);
2349        UINT8_TO_BE_STREAM (p, p_ret->lock_tlv[0]);
2350        UINT8_TO_BE_STREAM (p, p_ret->lock_tlv[1]);
2351        p = p_t1t->ndef_final_block;
2352        UINT8_TO_BE_STREAM (p, p_ret->lock_tlv[2]);
2353        UINT8_TO_BE_STREAM (p, TAG_MEM_CTRL_TLV);
2354        UINT8_TO_BE_STREAM (p, T1T_DEFAULT_TLV_LEN);
2355        UINT8_TO_BE_STREAM (p, p_ret->mem_tlv[0]);
2356        UINT8_TO_BE_STREAM (p, p_ret->mem_tlv[1]);
2357        UINT8_TO_BE_STREAM (p, p_ret->mem_tlv[2]);
2358    }
2359    /* Prepare NULL NDEF TLV */
2360    UINT8_TO_BE_STREAM (p, TAG_NDEF_TLV);
2361    UINT8_TO_BE_STREAM (p, 0);
2362
2363    if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN)
2364    {
2365        /* send WRITE-E8 command */
2366        if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_E8, 1, p_t1t->ndef_first_block)) == NFC_STATUS_OK)
2367        {
2368            p_t1t->state    = RW_T1T_STATE_FORMAT_TAG;
2369            p_t1t->b_update = FALSE;
2370            p_t1t->b_rseg   = FALSE;
2371            if (p_ret->b_dynamic)
2372                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_CC;
2373            else
2374                p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_NULL_NDEF;
2375        }
2376    }
2377    else
2378    {
2379        /* send WRITE-E command */
2380        RW_T1T_BLD_ADD ((addr), 1, 0);
2381
2382        if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, p_t1t->ndef_first_block[0])) == NFC_STATUS_OK)
2383        {
2384            p_t1t->work_offset  = 0;
2385            p_t1t->state        = RW_T1T_STATE_FORMAT_TAG;
2386            p_t1t->substate     = RW_T1T_SUBSTATE_WAIT_SET_NULL_NDEF;
2387            p_t1t->b_update     = FALSE;
2388            p_t1t->b_rseg       = FALSE;
2389        }
2390    }
2391
2392    return status;
2393}
2394
2395/*******************************************************************************
2396**
2397** Function         RW_T1tLocateTlv
2398**
2399** Description      This function is called to find the start of the given TLV
2400**
2401** Parameters:      tlv_type, Type of TLV to find
2402**
2403** Returns          NCI_STATUS_OK, if detection was started. Otherwise, error status.
2404**
2405*******************************************************************************/
2406tNFC_STATUS RW_T1tLocateTlv (UINT8 tlv_type)
2407{
2408    tNFC_STATUS     status = NFC_STATUS_FAILED;
2409    tRW_T1T_CB      *p_t1t= &rw_cb.tcb.t1t;
2410    UINT8           adds;
2411
2412    if (p_t1t->state != RW_T1T_STATE_IDLE)
2413    {
2414        RW_TRACE_WARNING1 ("RW_T1tLocateTlv - Busy - State: %u", p_t1t->state);
2415        return (NFC_STATUS_FAILED);
2416    }
2417    p_t1t->tlv_detect = tlv_type;
2418
2419    if(  (p_t1t->tlv_detect == TAG_NDEF_TLV)
2420       &&(((p_t1t->hr[0]) & 0xF0) != T1T_NDEF_SUPPORTED)  )
2421    {
2422        RW_TRACE_ERROR0 ("RW_T1tLocateTlv - Error: NDEF not supported by the tag");
2423        return (NFC_STATUS_REFUSED);
2424    }
2425
2426    if (  (p_t1t->tlv_detect == TAG_MEM_CTRL_TLV)
2427        ||(p_t1t->tlv_detect == TAG_NDEF_TLV)  )
2428    {
2429        p_t1t->num_mem_tlvs = 0;
2430    }
2431
2432    if (  (p_t1t->tlv_detect == TAG_LOCK_CTRL_TLV)
2433        ||(p_t1t->tlv_detect == TAG_NDEF_TLV)  )
2434    {
2435        p_t1t->num_lockbytes = 0;
2436        p_t1t->num_lock_tlvs = 0;
2437    }
2438
2439    /* Start reading memory, looking for the TLV */
2440    p_t1t->segment = 0;
2441    if ((p_t1t->hr[0] & 0x0F) != 1)
2442    {
2443        /* send RSEG command */
2444        RW_T1T_BLD_ADDS ((adds), (p_t1t->segment));
2445        status = rw_t1t_send_dyn_cmd (T1T_CMD_RSEG, adds, NULL);
2446    }
2447    else
2448    {
2449        status = rw_t1t_send_static_cmd (T1T_CMD_RALL, 0, 0);
2450    }
2451    if (status == NFC_STATUS_OK)
2452    {
2453        p_t1t->tlv_detect   = tlv_type;
2454        p_t1t->work_offset  = 0;
2455        p_t1t->state        = RW_T1T_STATE_TLV_DETECT;
2456        p_t1t->substate     = RW_T1T_SUBSTATE_NONE;
2457    }
2458
2459    return status;
2460}
2461
2462/*****************************************************************************
2463**
2464** Function         RW_T1tDetectNDef
2465**
2466** Description
2467**      This function is used to perform NDEF detection on a Type 1 tag, and
2468**      retrieve the tag's NDEF attribute information (block 0).
2469**
2470**      Before using this API, the application must call RW_SelectTagType to
2471**      indicate that a Type 1 tag has been activated.
2472**
2473** Returns
2474**      NFC_STATUS_OK: ndef detection procedure started
2475**      NFC_STATUS_WRONG_PROTOCOL: type 1 tag not activated
2476**      NFC_STATUS_BUSY: another command is already in progress
2477**      NFC_STATUS_FAILED: other error
2478**
2479*****************************************************************************/
2480tNFC_STATUS RW_T1tDetectNDef (void)
2481{
2482    return RW_T1tLocateTlv (TAG_NDEF_TLV);
2483}
2484
2485/*******************************************************************************
2486**
2487** Function         RW_T1tReadNDef
2488**
2489** Description      This function can be called to read the NDEF message on the tag.
2490**
2491** Parameters:      p_buffer:   The buffer into which to read the NDEF message
2492**                  buf_len:    The length of the buffer
2493**
2494** Returns          NCI_STATUS_OK, if read was started. Otherwise, error status.
2495**
2496*******************************************************************************/
2497tNFC_STATUS RW_T1tReadNDef (UINT8 *p_buffer, UINT16 buf_len)
2498{
2499    tNFC_STATUS     status = NFC_STATUS_FAILED;
2500    tRW_T1T_CB      *p_t1t = &rw_cb.tcb.t1t;
2501    BOOLEAN         b_notify;
2502    UINT8           adds;
2503    const tT1T_CMD_RSP_INFO *p_cmd_rsp_info_rall = t1t_cmd_to_rsp_info (T1T_CMD_RALL);
2504    const tT1T_CMD_RSP_INFO *p_cmd_rsp_info_rseg = t1t_cmd_to_rsp_info (T1T_CMD_RSEG);
2505
2506
2507
2508    if (p_t1t->state != RW_T1T_STATE_IDLE)
2509    {
2510        RW_TRACE_WARNING1 ("RW_T1tReadNDef - Busy - State: %u", p_t1t->state);
2511        return (NFC_STATUS_FAILED);
2512    }
2513
2514    /* Check HR0 if NDEF supported by the tag */
2515    if (((p_t1t->hr[0]) & 0xF0) != T1T_NDEF_SUPPORTED)
2516    {
2517        RW_TRACE_ERROR0 ("RW_T1tReadNDef - Error: NDEF not supported by the tag");
2518        return (NFC_STATUS_REFUSED);
2519    }
2520
2521    if (p_t1t->tag_attribute  == RW_T1_TAG_ATTRB_INITIALIZED_NDEF)
2522    {
2523        RW_TRACE_WARNING1 ("RW_T1tReadNDef - NDEF Message length is zero, NDEF Length : %u ", p_t1t->ndef_msg_len);
2524        return (NFC_STATUS_NOT_INITIALIZED);
2525    }
2526
2527    if (  (p_t1t->tag_attribute != RW_T1_TAG_ATTRB_READ_WRITE)
2528        &&(p_t1t->tag_attribute != RW_T1_TAG_ATTRB_READ_ONLY)  )
2529    {
2530        RW_TRACE_ERROR0 ("RW_T1tReadNDef - Error: NDEF detection not performed yet/ Tag is in Initialized state");
2531        return (NFC_STATUS_FAILED);
2532    }
2533
2534    if (buf_len < p_t1t->ndef_msg_len)
2535    {
2536        RW_TRACE_WARNING2 ("RW_T1tReadNDef - buffer size: %u  less than NDEF msg sise: %u", buf_len, p_t1t->ndef_msg_len);
2537        return (NFC_STATUS_FAILED);
2538    }
2539    p_t1t->p_ndef_buffer = p_buffer;
2540
2541    if (p_t1t->b_rseg == TRUE)
2542    {
2543        /* If already got response to RSEG 0 */
2544        p_t1t->state = RW_T1T_STATE_READ_NDEF;
2545        p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *)p_cmd_rsp_info_rseg;
2546
2547        rw_t1t_handle_read_rsp (&b_notify,p_t1t->mem);
2548        status       = NFC_STATUS_OK;
2549    }
2550    else if (p_t1t->b_update == TRUE)
2551    {
2552        /* If already got response to RALL */
2553        p_t1t->state = RW_T1T_STATE_READ_NDEF;
2554        p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) p_cmd_rsp_info_rall;
2555
2556        rw_t1t_handle_read_rsp (&b_notify,p_t1t->mem);
2557        status       = NFC_STATUS_OK;
2558
2559    }
2560    else
2561    {
2562        p_t1t->segment      = 0;
2563        p_t1t->work_offset  = 0;
2564        if ((p_t1t->hr[0] & 0x0F) != 1)
2565        {
2566            /* send RSEG command */
2567            RW_T1T_BLD_ADDS ((adds), (p_t1t->segment));
2568            status = rw_t1t_send_dyn_cmd (T1T_CMD_RSEG, adds, NULL);
2569        }
2570        else
2571        {
2572            status = rw_t1t_send_static_cmd (T1T_CMD_RALL, 0, 0);
2573        }
2574        if (status == NFC_STATUS_OK)
2575            p_t1t->state = RW_T1T_STATE_READ_NDEF;
2576
2577    }
2578
2579    return status;
2580}
2581
2582/*******************************************************************************
2583**
2584** Function         RW_T1tWriteNDef
2585**
2586** Description      This function can be called to write an NDEF message to the tag.
2587**
2588** Parameters:      msg_len:    The length of the buffer
2589**                  p_msg:      The NDEF message to write
2590**
2591** Returns          NCI_STATUS_OK, if write was started. Otherwise, error status.
2592**
2593*******************************************************************************/
2594tNFC_STATUS RW_T1tWriteNDef (UINT16 msg_len, UINT8 *p_msg)
2595{
2596    tNFC_STATUS status          = NFC_STATUS_FAILED;
2597    tRW_T1T_CB  *p_t1t          = &rw_cb.tcb.t1t;
2598    UINT16      num_ndef_bytes;
2599    UINT16      offset;
2600    UINT8       addr;
2601    UINT8       init_lengthfield_len;
2602    UINT8       new_lengthfield_len;
2603    UINT16      init_ndef_msg_offset;
2604
2605    if (p_t1t->state != RW_T1T_STATE_IDLE)
2606    {
2607        RW_TRACE_WARNING1 ("RW_T1tWriteNDef - Busy - State: %u", p_t1t->state);
2608        return (NFC_STATUS_FAILED);
2609    }
2610
2611    /* Check HR0 if NDEF supported by the tag */
2612    if (((p_t1t->hr[0]) & 0xF0) != T1T_NDEF_SUPPORTED)
2613    {
2614        RW_TRACE_ERROR0 ("RW_T1tWriteNDef - Error: NDEF not supported by the tag");
2615        return (NFC_STATUS_REFUSED);
2616    }
2617
2618    if (  (p_t1t->tag_attribute  != RW_T1_TAG_ATTRB_READ_WRITE)
2619        &&(p_t1t->tag_attribute  != RW_T1_TAG_ATTRB_INITIALIZED_NDEF)  )
2620    {
2621        RW_TRACE_ERROR0 ("RW_T1tWriteNDef - Tag cannot update NDEF");
2622        return (NFC_STATUS_REFUSED);
2623    }
2624
2625    if (msg_len > p_t1t->max_ndef_msg_len)
2626    {
2627        RW_TRACE_ERROR1 ("RW_T1tWriteNDef - Cannot write NDEF of size greater than %u bytes", p_t1t->max_ndef_msg_len);
2628        return (NFC_STATUS_REFUSED);
2629    }
2630
2631    p_t1t->p_ndef_buffer        = p_msg;
2632    p_t1t->new_ndef_msg_len     = msg_len;
2633    new_lengthfield_len         = p_t1t->new_ndef_msg_len > 254 ? 3:1;
2634    init_lengthfield_len        = (UINT8) (p_t1t->ndef_msg_offset - p_t1t->ndef_header_offset);
2635    init_ndef_msg_offset        = p_t1t->ndef_msg_offset;
2636
2637    /* ndef_msg_offset should reflect the new ndef message offset */
2638    if (init_lengthfield_len > new_lengthfield_len)
2639    {
2640        p_t1t->ndef_msg_offset  =  init_ndef_msg_offset - (T1T_LONG_NDEF_LEN_FIELD_LEN - T1T_SHORT_NDEF_LEN_FIELD_LEN);
2641    }
2642    else if (init_lengthfield_len < new_lengthfield_len)
2643    {
2644        p_t1t->ndef_msg_offset  =  init_ndef_msg_offset + (T1T_LONG_NDEF_LEN_FIELD_LEN - T1T_SHORT_NDEF_LEN_FIELD_LEN);
2645    }
2646
2647    num_ndef_bytes              = 0;
2648    offset                      = p_t1t->ndef_msg_offset;
2649    p_t1t->segment              = (UINT8) (p_t1t->ndef_msg_offset/T1T_SEGMENT_SIZE);
2650
2651    /* Locate NDEF final block based on the size of new NDEF Message */
2652    while (num_ndef_bytes < p_t1t->new_ndef_msg_len)
2653    {
2654        if (rw_t1t_is_lock_reserved_otp_byte ((UINT16) offset) == FALSE)
2655            num_ndef_bytes++;
2656
2657        offset++;
2658        if (offset % T1T_SEGMENT_SIZE == 0)
2659        {
2660            p_t1t->segment      = (UINT8) (offset / T1T_SEGMENT_SIZE);
2661        }
2662    }
2663
2664    p_t1t->b_update = FALSE;
2665    p_t1t->b_rseg   = FALSE;
2666
2667    if ((p_t1t->hr[0] & 0x0F) != 1)
2668    {
2669        /* Dynamic data structure */
2670        p_t1t->block_read = (UINT8) ((offset - 1)/T1T_BLOCK_SIZE);
2671        /* Read NDEF final block before updating */
2672        if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_READ8, p_t1t->block_read, NULL)) == NFC_STATUS_OK)
2673        {
2674            p_t1t->num_ndef_finalblock = p_t1t->block_read;
2675            p_t1t->state    = RW_T1T_STATE_WRITE_NDEF;
2676            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_READ_NDEF_BLOCK;
2677        }
2678    }
2679    else
2680    {
2681        /* NDEF detected and Static memory structure so send WRITE-E command */
2682        RW_T1T_BLD_ADD ((addr), (T1T_CC_BLOCK), (T1T_CC_NMN_OFFSET));
2683        if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, 0)) == NFC_STATUS_OK)
2684        {
2685            p_t1t->state    = RW_T1T_STATE_WRITE_NDEF;
2686            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_INVALIDATE_NDEF;
2687        }
2688
2689    }
2690
2691    if (status != NFC_STATUS_OK)
2692    {
2693        /* if status failed, reset ndef_msg_offset to initial message */
2694        p_t1t->ndef_msg_offset = init_ndef_msg_offset;
2695    }
2696    return status;
2697}
2698
2699/*******************************************************************************
2700**
2701** Function         RW_T1tSetTagReadOnly
2702**
2703** Description      This function can be called to set t1 tag as read only.
2704**
2705** Parameters:      None
2706**
2707** Returns          NCI_STATUS_OK, if setting tag as read only was started.
2708**                  Otherwise, error status.
2709**
2710*******************************************************************************/
2711tNFC_STATUS RW_T1tSetTagReadOnly (BOOLEAN b_hard_lock)
2712{
2713    tNFC_STATUS status      = NFC_STATUS_FAILED;
2714    tRW_T1T_CB  *p_t1t      = &rw_cb.tcb.t1t;
2715    UINT8       addr;
2716    UINT8       num_locks;
2717
2718    if (p_t1t->state != RW_T1T_STATE_IDLE)
2719    {
2720        RW_TRACE_WARNING1 ("RW_T1tSetTagReadOnly - Busy - State: %u", p_t1t->state);
2721        return (NFC_STATUS_BUSY);
2722    }
2723
2724    p_t1t->b_hard_lock = b_hard_lock;
2725
2726    if (  (p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_WRITE)
2727        ||(p_t1t->tag_attribute == RW_T1_TAG_ATTRB_INITIALIZED)
2728        ||(p_t1t->tag_attribute == RW_T1_TAG_ATTRB_INITIALIZED_NDEF)  )
2729    {
2730        /* send WRITE-NE command */
2731        RW_T1T_BLD_ADD ((addr), (T1T_CC_BLOCK), (T1T_CC_RWA_OFFSET));
2732        if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_NE, addr, 0x0F)) == NFC_STATUS_OK)
2733        {
2734            p_t1t->b_update = FALSE;
2735            p_t1t->b_rseg   = FALSE;
2736
2737            if (p_t1t->b_hard_lock)
2738            {
2739                num_locks = 0;
2740                while (num_locks < p_t1t->num_lockbytes)
2741                {
2742                    p_t1t->lockbyte[num_locks].lock_status = RW_T1T_LOCK_NOT_UPDATED;
2743                    num_locks++;
2744                }
2745            }
2746            p_t1t->state    = RW_T1T_STATE_SET_TAG_RO;
2747            p_t1t->substate = RW_T1T_SUBSTATE_WAIT_SET_CC_RWA_RO;
2748        }
2749    }
2750
2751    return status;
2752}
2753
2754#if (BT_TRACE_VERBOSE == TRUE)
2755/*******************************************************************************
2756**
2757** Function         rw_t1t_get_sub_state_name
2758**
2759** Description      This function returns the sub_state name.
2760**
2761** NOTE             conditionally compiled to save memory.
2762**
2763** Returns          pointer to the name
2764**
2765*******************************************************************************/
2766static char *rw_t1t_get_sub_state_name (UINT8 sub_state)
2767{
2768    switch (sub_state)
2769    {
2770    case RW_T1T_SUBSTATE_NONE:
2771        return ("NONE");
2772    case RW_T1T_SUBSTATE_WAIT_READ_TLV_VALUE:
2773        return ("EXTRACT_TLV_VALUE");
2774    case RW_T1T_SUBSTATE_WAIT_READ_LOCKS:
2775        return ("READING_LOCKS");
2776    case RW_T1T_SUBSTATE_WAIT_READ_NDEF_BLOCK:
2777        return ("READ_NDEF_FINAL_BLOCK");
2778    case RW_T1T_SUBSTATE_WAIT_INVALIDATE_NDEF:
2779        return ("INVALIDATING_NDEF");
2780    case RW_T1T_SUBSTATE_WAIT_NDEF_WRITE:
2781        return ("WRITE_NDEF_TLV_MESSAGE");
2782    case RW_T1T_SUBSTATE_WAIT_NDEF_UPDATED:
2783        return ("WAITING_RSP_FOR_LAST_NDEF_WRITE");
2784    case RW_T1T_SUBSTATE_WAIT_VALIDATE_NDEF:
2785        return ("VALIDATING_NDEF");
2786    case RW_T1T_SUBSTATE_WAIT_SET_CC_RWA_RO:
2787        return ("SET_RWA_RO");
2788    case RW_T1T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
2789        return ("SET_STATIC_LOCK_BITS");
2790    case RW_T1T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
2791        return ("SET_DYNAMIC_LOCK_BITS");
2792
2793    default:
2794        return ("???? UNKNOWN SUBSTATE");
2795    }
2796}
2797#endif /* (BT_TRACE_VERBOSE == TRUE) */
2798
2799#endif /* (defined ((RW_NDEF_INCLUDED) && (RW_NDEF_INCLUDED == TRUE)) */
2800
2801#endif /* (NFC_INCLUDED == TRUE) */
2802