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