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