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