blob: 7562bf07335b26e1f7cd354e1b3a99961dac7937 [file] [log] [blame]
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001/******************************************************************************
2 *
Evan Chue9629ba2014-01-31 11:18:47 -05003 * Copyright (C) 2010-2014 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
19/******************************************************************************
20 *
21 * This file contains the implementation for Type 2 tag NDEF operation in
22 * Reader/Writer mode.
23 *
24 ******************************************************************************/
25#include <string.h>
26#include "nfc_target.h"
27
28#if (NFC_INCLUDED == TRUE)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080029#include "gki.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080030#include "nci_hmsgs.h"
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080031#include "nfc_api.h"
32#include "nfc_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080033#include "rw_api.h"
34#include "rw_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080035
Ruchi Kandoi303fec12016-12-14 13:22:38 -080036#if (RW_NDEF_INCLUDED == TRUE)
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080037
38/* Local static functions */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080039static void rw_t2t_handle_cc_read_rsp(void);
40static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data);
41static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data);
42static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data);
43static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data);
44static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data);
45static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data);
46static uint8_t rw_t2t_get_tag_size(uint8_t* p_data);
47static void rw_t2t_extract_default_locks_info(void);
48static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
49 bool b_update_len);
50static uint8_t rw_t2t_get_ndef_flags(void);
51static uint16_t 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 bool rw_t2t_is_lock_res_byte(uint16_t index);
57static bool rw_t2t_is_read_only_byte(uint16_t index);
58static tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len,
59 bool b_update_len);
60static tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block,
61 uint16_t msg_len,
62 bool b_update_len);
63static tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block);
64static tNFC_STATUS rw_t2t_add_terminator_tlv(void);
65static bool rw_t2t_is_read_before_write_block(uint16_t block,
66 uint16_t* p_block_to_read);
67static tNFC_STATUS rw_t2t_set_cc(uint8_t tms);
68static tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
69 uint16_t locked_area_size);
70static tNFC_STATUS rw_t2t_format_tag(void);
71static tNFC_STATUS rw_t2t_soft_lock_tag(void);
72static tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data);
73static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080074
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080075const uint8_t rw_t2t_mask_bits[8] = {0x01, 0x02, 0x04, 0x08,
76 0x10, 0x20, 0x40, 0x80};
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080077
78/*******************************************************************************
79**
80** Function rw_t2t_handle_rsp
81**
82** Description This function handles response to command sent during
83** NDEF and other tlv operation
84**
85** Returns None
86**
87*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080088void rw_t2t_handle_rsp(uint8_t* p_data) {
89 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080090
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080091 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
92 p_t2t->b_read_hdr = true;
93 memcpy(p_t2t->tag_hdr, p_data, T2T_READ_DATA_LEN);
94 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080095
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080096 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080097 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080098 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
99 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
100 rw_t2t_handle_cc_read_rsp();
101 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
102 rw_t2t_handle_lock_read_rsp(p_data);
103 } else {
104 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800105 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800106 } else if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
107 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
108 if (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] == T2T_CC0_NMN) {
109 rw_t2t_handle_cc_read_rsp();
110 } else {
111 RW_TRACE_WARNING3(
112 "NDEF Detection failed!, CC[0]: 0x%02x, CC[1]: 0x%02x, CC[3]: "
113 "0x%02x",
114 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE],
115 p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
116 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
117 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
118 }
119 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
120 rw_t2t_handle_lock_read_rsp(p_data);
121 } else {
122 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800123 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800124 } else {
125 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
126 rw_t2t_handle_cc_read_rsp();
127 } else {
128 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800129 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800130 }
131 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800132
133 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800134 rw_t2t_handle_config_tag_readonly(p_data);
135 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800136
137 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800138 rw_t2t_handle_format_tag_rsp(p_data);
139 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800140
141 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800142 rw_t2t_handle_ndef_read_rsp(p_data);
143 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800144
145 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800146 rw_t2t_handle_ndef_write_rsp(p_data);
147 break;
148 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800149}
150
151/*******************************************************************************
152**
153** Function rw_t2t_info_to_event
154**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800155** Description This function returns RW event code based on the current
156** state
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800157**
158** Returns RW event code
159**
160*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800161tRW_EVENT rw_t2t_info_to_event(const tT2T_CMD_RSP_INFO* p_info) {
162 tRW_EVENT rw_event;
163 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800164
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800165 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800166 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800167 if (p_t2t->tlv_detect == TAG_NDEF_TLV)
168 rw_event = RW_T2T_NDEF_DETECT_EVT;
169 else
170 rw_event = RW_T2T_TLV_DETECT_EVT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800171
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800172 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800173
174 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800175 rw_event = RW_T2T_NDEF_READ_EVT;
176 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800177
178 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800179 rw_event = RW_T2T_NDEF_WRITE_EVT;
180 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800181
182 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800183 rw_event = RW_T2T_SET_TAG_RO_EVT;
184 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800185
186 case RW_T2T_STATE_CHECK_PRESENCE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800187 rw_event = RW_T2T_PRESENCE_CHECK_EVT;
188 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800189
190 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800191 rw_event = RW_T2T_FORMAT_CPLT_EVT;
192 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800193
194 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800195 rw_event = t2t_info_to_evt(p_info);
196 break;
197 }
198 return rw_event;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800199}
200
201/*******************************************************************************
202**
203** Function rw_t2t_handle_cc_read_rsp
204**
205** Description Handle read cc bytes
206**
207** Returns none
208**
209*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800210static void rw_t2t_handle_cc_read_rsp(void) {
211 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800212
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800213 if (((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) &&
214 (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RO)) ||
215 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
216 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
217 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
218 /* Invalid Version number or RWA byte */
219 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
220 return;
221 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800222
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800223 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800224
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800225 if (rw_t2t_read((uint16_t)T2T_FIRST_DATA_BLOCK) != NFC_STATUS_OK) {
226 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
227 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800228}
229
230/*******************************************************************************
231**
232** Function rw_t2t_ntf_tlv_detect_complete
233**
234** Description Notify TLV detection complete to upper layer
235**
236** Returns none
237**
238*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800239static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status) {
240 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
241 tRW_DETECT_NDEF_DATA ndef_data = {
242 0,
243 };
244 tRW_DETECT_TLV_DATA tlv_data;
245 tRW_T2T_DETECT evt_data;
246 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800247
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800248 if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
249 /* Notify upper layer the result of NDEF detect op */
250 ndef_data.status = status;
251 ndef_data.protocol = NFC_PROTOCOL_T2T;
252 ndef_data.flags = rw_t2t_get_ndef_flags();
253 ndef_data.cur_size = p_t2t->ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800254
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800255 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_FORMATED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800256
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800257 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] == T2T_CC3_RWA_RW)
258 ndef_data.max_size = (uint32_t)rw_t2t_get_ndef_max_size();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800259 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800260 ndef_data.max_size = ndef_data.cur_size;
261
262 if (ndef_data.max_size < ndef_data.cur_size) {
263 ndef_data.flags |= RW_NDEF_FL_READ_ONLY;
264 ndef_data.max_size = ndef_data.cur_size;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800265 }
266
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800267 if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY)) {
268 ndef_data.flags |= RW_NDEF_FL_SOFT_LOCKABLE;
269 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_HARD_LOCKABLE;
270 }
271
272 rw_t2t_handle_op_complete();
273 (*rw_cb.p_cback)(RW_T2T_NDEF_DETECT_EVT, (tRW_DATA*)&ndef_data);
274 } else if (p_t2t->tlv_detect == TAG_PROPRIETARY_TLV) {
275 evt_data.msg_len = p_t2t->prop_msg_len;
276 evt_data.status = status;
277 rw_t2t_handle_op_complete();
278 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, (tRW_DATA*)&evt_data);
279 } else {
280 /* Notify upper layer the result of Lock/Mem TLV detect op */
281 tlv_data.protocol = NFC_PROTOCOL_T2T;
282 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
283 tlv_data.num_bytes = p_t2t->num_lockbytes;
284 } else {
285 tlv_data.num_bytes = 0;
286 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++) {
287 tlv_data.num_bytes += p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes;
288 }
289 }
290 tlv_data.status = status;
291 rw_t2t_handle_op_complete();
292 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, (tRW_DATA*)&tlv_data);
293 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800294}
295
296/*******************************************************************************
297**
298** Function rw_t2t_handle_lock_read_rsp
299**
300** Description Handle response to reading lock bytes
301**
302** Returns none
303**
304*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800305static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data) {
306 uint8_t updated_lock_byte;
307 uint8_t num_locks;
308 uint8_t offset = 0;
309 uint16_t lock_offset;
310 uint16_t base_lock_offset = 0;
311 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
312 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800313
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800314 /* Prepare NDEF/TLV attributes (based on current op) for sending response to
315 * upper layer */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800316
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800317 num_locks = 0;
318 updated_lock_byte = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800319
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800320 /* Extract all lock bytes present in the read 16 bytes
321 * but atleast one lock byte (base lock) should be present in the read 16
322 * bytes */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800323
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800324 while (num_locks < p_t2t->num_lockbytes) {
325 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
326 lock_offset =
327 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
328 p_t2t->lockbyte[num_locks].byte_index;
329 if (updated_lock_byte == 0) {
330 /* The offset of the first lock byte present in the 16 bytes read using
331 * READ command */
332 base_lock_offset = lock_offset;
333 /* Block number used to read may not be the block where lock offset is
334 * present */
335 offset = (uint8_t)(lock_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
336 /* Update the lock byte value in the control block */
337 p_t2t->lockbyte[num_locks].lock_byte = p_data[offset];
338 p_t2t->lockbyte[num_locks].b_lock_read = true;
339 updated_lock_byte++;
340 } else if (lock_offset > base_lock_offset) {
341 /* Atleast one lock byte will get updated in the control block */
342 if ((lock_offset - base_lock_offset + offset) < T2T_READ_DATA_LEN) {
343 /* And this lock byte is also present in the read data */
344 p_t2t->lockbyte[num_locks].lock_byte =
345 p_data[lock_offset - base_lock_offset + offset];
346 p_t2t->lockbyte[num_locks].b_lock_read = true;
347 updated_lock_byte++;
348 } else {
349 /* This lock byte is not present in the read data */
350 block = (uint16_t)(lock_offset / T2T_BLOCK_LEN);
351 block -= block % T2T_READ_BLOCKS;
352 /* send READ command to read this lock byte */
353 if (NFC_STATUS_OK != rw_t2t_read((uint16_t)block)) {
354 /* Unable to send Read command, notify failure status to upper layer
355 */
356 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
357 }
358 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800359 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800360 } else {
361 /* This Lock byte is not present in the read 16 bytes
362 * send READ command to read the lock byte */
363 if (NFC_STATUS_OK !=
364 rw_t2t_read((uint16_t)(lock_offset / T2T_BLOCK_LEN))) {
365 /* Unable to send Read command, notify failure status to upper layer
366 */
367 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
368 }
369 break;
370 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800371 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800372 num_locks++;
373 }
374 if (num_locks == p_t2t->num_lockbytes) {
375 /* All locks are read, notify upper layer */
376 rw_t2t_update_lock_attributes();
377 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_OK);
378 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800379}
380
381/*******************************************************************************
382**
383** Function rw_t2t_handle_tlv_detect_rsp
384**
385** Description Handle TLV detection.
386**
387** Returns none
388**
389*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800390static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data) {
391 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
392 uint16_t offset;
393 uint16_t len = 0;
394 bool failed = false;
395 bool found = false;
396 tRW_EVENT event;
397 uint8_t index;
398 uint8_t count = 0;
399 uint8_t xx;
400 tNFC_STATUS status;
401 tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
402 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
403 uint8_t tlvtype = p_t2t->tlv_detect;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800404
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800405 if (p_t2t->work_offset == 0) {
406 /* Skip UID,Static Lock block,CC*/
407 p_t2t->work_offset = T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN;
408 p_t2t->b_read_data = true;
409 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
410 }
411
412 p_t2t->segment = 0;
413
414 for (offset = 0; offset < T2T_READ_DATA_LEN && !failed && !found;) {
415 if (rw_t2t_is_lock_res_byte((uint16_t)(p_t2t->work_offset + offset)) ==
416 true) {
417 /* Skip locks, reserved bytes while searching for TLV */
418 offset++;
419 continue;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800420 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800421 switch (p_t2t->substate) {
422 case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
423 /* Search for the tlv */
424 p_t2t->found_tlv = p_data[offset++];
425 switch (p_t2t->found_tlv) {
426 case TAG_NULL_TLV: /* May be used for padding. SHALL ignore this */
427 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800428
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800429 case TAG_NDEF_TLV:
430 if (tlvtype == TAG_NDEF_TLV) {
431 /* NDEF Detected, now collect NDEF Attributes including NDEF
432 * Length */
433 index = (offset % T2T_BLOCK_SIZE);
434 /* Backup ndef first block */
435 memcpy(p_t2t->ndef_first_block, &p_data[offset - index], index);
436 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
437 } else if (tlvtype == TAG_PROPRIETARY_TLV) {
438 /* Proprietary TLV can exist after NDEF Tlv so we continue
439 * searching */
440 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
441 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
442 (p_t2t->num_lockbytes > 0)) ||
443 ((tlvtype == TAG_MEM_CTRL_TLV) &&
444 (p_t2t->num_mem_tlvs > 0))) {
445 /* Lock / Memory control tlv cannot exist after NDEF TLV
446 * So when NDEF is found, we stop searching for Lock and Memory
447 * control tlv */
448 found = true;
449 } else {
450 /* While searching for Lock / Memory control tlv, if NDEF TLV is
451 * found
452 * first then our search for Lock /Memory control tlv failed and
453 * we stop here */
454 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800455 }
456 break;
457
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800458 case TAG_LOCK_CTRL_TLV:
459 case TAG_MEM_CTRL_TLV:
460 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
461 break;
462
463 case TAG_PROPRIETARY_TLV:
464 if (tlvtype == TAG_PROPRIETARY_TLV) {
465 index = (offset % T2T_BLOCK_SIZE);
466 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
467 } else {
468 /* NDEF/LOCK/MEM TLV can exist after Proprietary Tlv so we
469 * continue searching, skiping proprietary tlv */
470 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
471 }
472 break;
473
474 case TAG_TERMINATOR_TLV: /* Last TLV block in the data area. Must be
475 no NDEF nessage */
476 if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
477 (p_t2t->num_lockbytes > 0)) ||
478 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
479 /* No more Lock/Memory TLV control tlv in the tag, so stop
480 * searching */
481 found = true;
482 } else {
483 /* NDEF/Lock/Memory/Proprietary TLV cannot exist after Terminator
484 * Tlv */
485 failed = true;
486 }
487 break;
488 default:
489 failed = true;
490 }
491 break;
492
493 case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
494 len = p_data[offset];
495 switch (p_t2t->found_tlv) {
496 case TAG_NDEF_TLV:
497 p_t2t->ndef_header_offset = offset + p_t2t->work_offset;
498 if (len == TAG_LONG_NDEF_LEN_FIELD_BYTE0) {
499 /* The next two bytes constitute length bytes */
500 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
501 } else {
502 /* one byte length field */
503 p_t2t->ndef_msg_len = len;
504 p_t2t->bytes_count = p_t2t->ndef_msg_len;
505 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
506 }
507 break;
508
509 case TAG_PROPRIETARY_TLV:
510 if (len == T2T_LONG_NDEF_LEN_FIELD_BYTE0) {
511 /* The next two bytes constitute length bytes */
512 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
513 } else {
514 /* one byte length field */
515 p_t2t->prop_msg_len = len;
516 p_t2t->bytes_count = p_t2t->prop_msg_len;
517 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
518 }
519 break;
520 }
521 offset++;
522 break;
523
524 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
525 switch (p_t2t->found_tlv) {
526 case TAG_LOCK_CTRL_TLV:
527 case TAG_MEM_CTRL_TLV:
528
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800529 len = p_data[offset];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800530 if (len == TAG_DEFAULT_TLV_LEN) {
531 /* Valid Lock control TLV */
532 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
533 p_t2t->bytes_count = TAG_DEFAULT_TLV_LEN;
534 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
535 (p_t2t->num_lockbytes > 0)) ||
536 ((tlvtype == TAG_MEM_CTRL_TLV) &&
537 (p_t2t->num_mem_tlvs > 0))) {
538 /* Stop searching for Lock/ Memory control tlv */
539 found = true;
540 } else {
541 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800542 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800543 break;
544
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800545 case TAG_NDEF_TLV:
546 case TAG_PROPRIETARY_TLV:
547 /* The first length byte */
548 p_t2t->bytes_count = (uint8_t)p_data[offset];
549 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800550 break;
551 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800552 offset++;
553 break;
554
555 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
556 /* Prepare NDEF Message length */
557 p_t2t->bytes_count = (p_t2t->bytes_count << 8) + p_data[offset];
558 if (p_t2t->found_tlv == TAG_NDEF_TLV) {
559 p_t2t->ndef_msg_len = p_t2t->bytes_count;
560 } else if (p_t2t->found_tlv == TAG_PROPRIETARY_TLV) {
561 p_t2t->prop_msg_len = p_t2t->bytes_count;
562 }
563 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
564 offset++;
565 break;
566
567 case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
568 switch (p_t2t->found_tlv) {
569 case TAG_NDEF_TLV:
570 if ((p_t2t->bytes_count == p_t2t->ndef_msg_len) &&
571 (tlvtype == TAG_NDEF_TLV)) {
572 /* The first byte offset after length field */
573 p_t2t->ndef_msg_offset = offset + p_t2t->work_offset;
574 }
575 /* Reduce number of NDEF bytes remaining to pass over NDEF TLV */
576 if (p_t2t->bytes_count > 0) p_t2t->bytes_count--;
577
578 if (tlvtype == TAG_NDEF_TLV) {
579 found = true;
580 p_t2t->ndef_status = T2T_NDEF_DETECTED;
581 } else if (p_t2t->bytes_count == 0) {
582 /* Next byte could be a different TLV */
583 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
584 }
585 break;
586
587 case TAG_LOCK_CTRL_TLV:
588 p_t2t->bytes_count--;
589 if ((tlvtype == TAG_LOCK_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
590 /* Collect Lock TLV */
591 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
592 if (p_t2t->bytes_count == 0) {
593 /* Lock TLV is collected and buffered in tlv_value, now decode
594 * it */
595 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
596 (p_t2t->tlv_value[0] >> 4) & 0x0F;
597 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset *=
598 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
599 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset +=
600 p_t2t->tlv_value[0] & 0x0F;
601 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
602 (uint8_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
603 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits =
604 p_t2t->tlv_value[1];
605 count = p_t2t->tlv_value[1] / 8 +
606 ((p_t2t->tlv_value[1] % 8 != 0) ? 1 : 0);
607
608 /* Extract lockbytes info addressed by this Lock TLV */
609 xx = 0;
610 while (xx < count) {
611 p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index =
612 p_t2t->num_lock_tlvs;
613 p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index = xx;
614 p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read = false;
615 xx++;
616 p_t2t->num_lockbytes++;
617 }
618 p_t2t->num_lock_tlvs++;
619 rw_t2t_update_attributes();
620 /* Next byte could be a different TLV */
621 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
622 }
623 } else {
624 /* If not looking for lock/ndef tlv, just skip this Lock TLV */
625 if (p_t2t->bytes_count == 0) {
626 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
627 }
628 }
629 break;
630
631 case TAG_MEM_CTRL_TLV:
632 p_t2t->bytes_count--;
633 if ((tlvtype == TAG_MEM_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
634 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
635 if (p_t2t->bytes_count == 0) {
636 if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS) {
637 RW_TRACE_ERROR0(
638 "rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated "
639 "for Memory tlv has reached");
640 failed = true;
641 } else {
642 /* Extract memory control tlv */
643 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
644 (p_t2t->tlv_value[0] >> 4) & 0x0F;
645 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
646 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
647 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
648 p_t2t->tlv_value[0] & 0x0F;
649 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
650 p_t2t->tlv_value[1];
651 p_t2t->num_mem_tlvs++;
652 rw_t2t_update_attributes();
653 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
654 }
655 }
656 } else {
657 if (p_t2t->bytes_count == 0) {
658 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
659 }
660 }
661 break;
662
663 case TAG_PROPRIETARY_TLV:
664 p_t2t->bytes_count--;
665 if (tlvtype == TAG_PROPRIETARY_TLV) {
666 found = true;
667 p_t2t->prop_msg_len = len;
668 } else {
669 if (p_t2t->bytes_count == 0) {
670 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
671 }
672 }
673 break;
674 }
675 offset++;
676 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800677 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800678 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800679
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800680 p_t2t->work_offset += T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800681
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800682 event = rw_t2t_info_to_event(p_cmd_rsp_info);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800683
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800684 /* If not found and not failed, read next block and search tlv */
685 if (!found && !failed) {
686 if (p_t2t->work_offset >=
687 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR)) {
688 if (((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0)) ||
689 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
690 found = true;
691 } else {
692 failed = true;
693 }
694 } else {
695 if (rw_t2t_read((uint16_t)((p_t2t->work_offset / T2T_BLOCK_LEN) +
696 T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
697 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800698 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800699 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800700
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800701 if (failed || found) {
702 if (tlvtype == TAG_LOCK_CTRL_TLV) {
703 /* Incase no Lock control tlv is present then look for default dynamic
704 * lock bytes */
705 rw_t2t_extract_default_locks_info();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800706
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800707 /* Send command to read the dynamic lock bytes */
708 status = rw_t2t_read_locks();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800709
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800710 if (status != NFC_STATUS_CONTINUE) {
711 /* If unable to read a lock/all locks read, notify upper layer */
712 rw_t2t_update_lock_attributes();
713 rw_t2t_ntf_tlv_detect_complete(status);
714 }
715 } else if (tlvtype == TAG_NDEF_TLV) {
716 rw_t2t_extract_default_locks_info();
717
718 if (failed) {
719 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
720 } else {
721 /* NDEF present,Send command to read the dynamic lock bytes */
722 status = rw_t2t_read_locks();
723 if (status != NFC_STATUS_CONTINUE) {
724 /* If unable to read a lock/all locks read, notify upper layer */
725 rw_t2t_update_lock_attributes();
726 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800727 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800728 }
729 } else {
730 /* Notify Memory/ Proprietary tlv detect result */
731 status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
732 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800733 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800734 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800735}
736
737/*******************************************************************************
738**
739** Function rw_t2t_read_locks
740**
741** Description This function will send command to read next unread locks
742**
743** Returns NFC_STATUS_OK, if all locks are read successfully
744** NFC_STATUS_FAILED, if reading locks failed
745** NFC_STATUS_CONTINUE, if reading locks is in progress
746**
747*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800748tNFC_STATUS rw_t2t_read_locks(void) {
749 uint8_t num_locks = 0;
750 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
751 tNFC_STATUS status = NFC_STATUS_CONTINUE;
752 uint16_t offset;
753 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800754
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800755 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) ||
756 (p_t2t->skip_dyn_locks)) {
757 /* Skip reading dynamic lock bytes if CC is set as Read only or layer above
758 * instructs to skip */
759 while (num_locks < p_t2t->num_lockbytes) {
760 p_t2t->lockbyte[num_locks].lock_byte = 0x00;
761 p_t2t->lockbyte[num_locks].b_lock_read = true;
762 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800763 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800764 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800765
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800766 while (num_locks < p_t2t->num_lockbytes) {
767 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
768 /* Send Read command to read the first un read locks */
769 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
770 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800771
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800772 /* Read 16 bytes where this lock byte is present */
773 block = (uint16_t)(offset / T2T_BLOCK_LEN);
774 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800775
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800776 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
777 /* send READ8 command */
778 if ((status = rw_t2t_read((uint16_t)block)) == NFC_STATUS_OK) {
779 /* Reading Locks */
780 status = NFC_STATUS_CONTINUE;
781 } else {
782 status = NFC_STATUS_FAILED;
783 }
784 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800785 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800786 num_locks++;
787 }
788 if (num_locks == p_t2t->num_lockbytes) {
789 /* All locks are read */
790 status = NFC_STATUS_OK;
791 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800792
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800793 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800794}
795
796/*******************************************************************************
797**
798** Function rw_t2t_extract_default_locks_info
799**
800** Description This function will prepare lockbytes information for default
801** locks present in the tag in the absence of lock control tlv.
802** Adding a virtual lock control tlv for these lock bytes for
803** easier manipulation.
804**
805** Returns None
806**
807*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800808void rw_t2t_extract_default_locks_info(void) {
809 uint8_t num_dynamic_lock_bits;
810 uint8_t num_dynamic_lock_bytes;
811 uint8_t xx;
812 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
813 const tT2T_INIT_TAG* p_ret;
814 uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800815
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800816 if ((p_t2t->num_lock_tlvs == 0) &&
817 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
818 /* No Lock control tlv is detected. Indicates lock bytes are present in
819 * default location */
820 /* Add a virtual Lock tlv to map this default lock location */
821 if ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL)
822 bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800823
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800824 num_dynamic_lock_bits =
825 ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
826 (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
827 bytes_locked_per_lock_bit;
828 num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
829 num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800830
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800831 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
832 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
833 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
834 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
835 bytes_locked_per_lock_bit;
836 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits = num_dynamic_lock_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800837
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800838 /* Based on tag data size the number of locks present in the default
839 * location changes */
840 for (xx = 0; xx < num_dynamic_lock_bytes; xx++) {
841 p_t2t->lockbyte[xx].tlv_index = p_t2t->num_lock_tlvs;
842 p_t2t->lockbyte[xx].byte_index = xx;
843 p_t2t->lockbyte[xx].b_lock_read = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800844 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800845 p_t2t->num_lockbytes = num_dynamic_lock_bytes;
846 p_t2t->num_lock_tlvs = 1;
847 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800848}
849
850/*******************************************************************************
851**
852** Function rw_t2t_read_ndef_last_block
853**
854** Description This function will locate and read the last ndef block.
855** The last ndef block refers to the tag block where last byte
856** of new ndef message will reside. Also this function will
857** locate the offset of Terminator TLV based on the size of
858** new NDEF Message
859**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800860** Returns NCI_STATUS_OK, if able to locate last ndef block & read
861** started. Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800862**
863*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800864tNFC_STATUS rw_t2t_read_ndef_last_block(void) {
865 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
866 uint16_t header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN)
867 ? T2T_LONG_NDEF_LEN_FIELD_LEN
868 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
869 uint16_t num_ndef_bytes;
870 uint16_t total_ndef_bytes;
871 uint16_t last_ndef_byte_offset;
872 uint16_t terminator_tlv_byte_index;
873 tNFC_STATUS status;
874 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800875
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800876 total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
877 num_ndef_bytes = 0;
878 last_ndef_byte_offset = p_t2t->ndef_header_offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800879
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800880 /* Locate NDEF final block based on the size of new NDEF Message */
881 while (num_ndef_bytes < total_ndef_bytes) {
882 if (rw_t2t_is_lock_res_byte((uint16_t)(last_ndef_byte_offset)) == false)
883 num_ndef_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800884
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800885 last_ndef_byte_offset++;
886 }
887 p_t2t->ndef_last_block_num =
888 (uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
889 block = p_t2t->ndef_last_block_num;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800890
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800891 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
892 /* Read NDEF last block before updating */
893 if ((status = rw_t2t_read(block)) == NFC_STATUS_OK) {
894 if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
895 /* Locate Terminator TLV Block */
896 total_ndef_bytes++;
897 terminator_tlv_byte_index = last_ndef_byte_offset;
898
899 while (num_ndef_bytes < total_ndef_bytes) {
900 if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
901 false)
902 num_ndef_bytes++;
903
904 terminator_tlv_byte_index++;
905 }
906
907 p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
908 } else {
909 /* No space for Terminator TLV */
910 p_t2t->terminator_byte_index = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800911 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800912 }
913 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800914}
915
916/*******************************************************************************
917**
918** Function rw_t2t_read_terminator_tlv_block
919**
920** Description This function will read the block where terminator tlv will
921** be added later
922**
923** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
924**
925*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800926tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
927 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
928 tNFC_STATUS status;
929 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800930
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800931 /* Send read command to read base block (Block % 4==0) where this block is
932 * also read as part of 16 bytes */
933 block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
934 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800935
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800936 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
937 /* Read the block where Terminator TLV may be added later during NDEF Write
938 * operation */
939 status = rw_t2t_read(block);
940 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800941}
942
943/*******************************************************************************
944**
945** Function rw_t2t_read_ndef_next_block
946**
947** Description This function will read the tag block passed as argument
948**
949** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
950**
951*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800952tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block) {
953 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
954 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800955
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800956 /* Send read command to read base block (Block % 4==0) where this block is
957 * also read as part of 16 bytes */
958 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800959
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800960 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
961 /* Read the block */
962 status = rw_t2t_read(block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800963
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800964 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800965}
966
967/*******************************************************************************
968**
969** Function rw_t2t_is_read_before_write_block
970**
971** Description This function will check if the block has to be read before
972** writting to avoid over writting in to lock/reserved bytes
973** present in the block.
974** If no bytes in the block can be overwritten it moves in to
975** next block and check. Finally it finds a block where part of
976** ndef bytes can exist and check if the whole block can be
977** updated or only part of block can be modified.
978**
979** Returns TRUE, if the block returned should be read before writting
980** FALSE, if the block need not be read as it was already
981** read or during NDEF write we may completely overwrite
982** the block and there is no reserved or locked bytes in
983** that block
984**
985*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800986static bool rw_t2t_is_read_before_write_block(uint16_t block,
987 uint16_t* p_block_to_read) {
988 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
989 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
990 uint8_t count;
991 uint8_t index;
992 uint16_t tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
993 bool read_before_write = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800994
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800995 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
996 /* First NDEF block is already read */
997 read_before_write = false;
998 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
999 } else if (block == p_t2t->ndef_last_block_num) {
1000 /* Last NDEF block is already read */
1001 read_before_write = false;
1002 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1003 } else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) {
1004 /* Terminator tlv block is already read */
1005 read_before_write = false;
1006 memcpy(p_t2t->ndef_read_block, p_t2t->terminator_tlv_block, T2T_BLOCK_SIZE);
1007 } else {
1008 count = 0;
1009 while (block < tag_size) {
1010 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001011
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001012 while (index < T2T_BLOCK_SIZE) {
1013 /* check if it is a reserved or locked byte */
1014 if (rw_t2t_is_lock_res_byte(
1015 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1016 count++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001017 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001018 index++;
1019 }
1020 if (count == T2T_BLOCK_SIZE) {
1021 /* All the bytes in the block are free to NDEF write */
1022 read_before_write = false;
1023 break;
1024 } else if (count == 0) {
1025 /* The complete block is not free for NDEF write */
1026 index = 0;
1027 block++;
1028 } else {
1029 /* The block has reseved byte (s) or locked byte (s) or both */
1030 read_before_write = true;
1031 break;
1032 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001033 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001034 }
1035 /* Return the block to read next before NDEF write */
1036 *p_block_to_read = block;
1037 return read_before_write;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001038}
1039
1040/*******************************************************************************
1041**
1042** Function rw_t2t_write_ndef_first_block
1043**
1044** Description This function will write the first NDEF block with Length
1045** field reset to zero.
1046** Also after writting NDEF this function may be called to
1047** update new NDEF length
1048**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001049** Returns NCI_STATUS_OK, if write was started.
1050** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001051**
1052*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001053tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len, bool b_update_len) {
1054 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1055 uint8_t new_lengthfield_len;
1056 uint8_t write_block[4];
1057 uint8_t block;
1058 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1059 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1060 tNFC_STATUS status;
1061 uint8_t length_field[3];
1062 uint8_t index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001063
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001064 p_t2t->work_offset = 0;
1065 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1066 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1067 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1068 if (new_lengthfield_len == 3) {
1069 /* New NDEF is Long NDEF */
1070 if (msg_len == 0) {
1071 /* Clear NDEF length field */
1072 length_field[0] = 0x00;
1073 length_field[1] = 0x00;
1074 length_field[2] = 0x00;
1075 } else {
1076 /* Update NDEF length field with new NDEF Msg len */
1077 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1078 length_field[1] = (uint8_t)(msg_len >> 8);
1079 length_field[2] = (uint8_t)(msg_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001080 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001081 } else {
1082 /* New NDEF is Short NDEF */
1083 length_field[0] = (uint8_t)(msg_len);
1084 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001085
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001086 /* updating ndef_first_block with new ndef message */
1087 memcpy(write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001088
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001089 index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1090 block = (uint8_t)(p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001091
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001092 while (p_t2t->work_offset == 0 && block < total_blocks) {
1093 /* update length field */
1094 while (index < T2T_BLOCK_SIZE &&
1095 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1096 if (rw_t2t_is_lock_res_byte(
1097 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1098 write_block[index] = length_field[p_t2t->work_offset];
1099 p_t2t->work_offset++;
1100 }
1101 index++;
1102 if (p_t2t->work_offset == new_lengthfield_len) {
1103 break;
1104 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001105 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001106 /* If more space in this block then add ndef message */
1107 while (index < T2T_BLOCK_SIZE &&
1108 p_t2t->work_offset <
1109 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1110 if (rw_t2t_is_lock_res_byte(
1111 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1112 write_block[index] =
1113 p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1114 p_t2t->work_offset++;
1115 }
1116 index++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001117 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001118 if (p_t2t->work_offset == 0) {
1119 /* If no bytes are written move to next block */
1120 index = 0;
1121 block++;
1122 if (block == p_t2t->ndef_last_block_num) {
1123 memcpy(write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1124 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001125 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001126 }
1127 if (p_t2t->work_offset == 0) {
1128 status = NFC_STATUS_FAILED;
1129 } else {
1130 rw_t2t_update_cb(block, write_block, b_update_len);
1131 /* Update the identified block with newly prepared data */
1132 if ((status = rw_t2t_write(block, write_block)) == NFC_STATUS_OK) {
1133 p_t2t->b_read_data = false;
1134 }
1135 }
1136 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001137}
1138
1139/*******************************************************************************
1140**
1141** Function rw_t2t_write_ndef_next_block
1142**
1143** Description This function can be called to write an NDEF message block
1144**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001145** Returns NCI_STATUS_OK, if write was started.
1146** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001147**
1148*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001149tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block, uint16_t msg_len,
1150 bool b_update_len) {
1151 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1152 uint8_t new_lengthfield_len;
1153 uint8_t write_block[4];
1154 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1155 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1156 uint16_t initial_offset;
1157 uint8_t length_field[3];
1158 uint8_t index;
1159 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001160
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001161 /* Write NDEF Message */
1162 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1163 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1164 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001165
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001166 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001167
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001168 memcpy(write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001169
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001170 if (p_t2t->work_offset >= new_lengthfield_len) {
1171 /* Length field is updated, write ndef message field */
1172 initial_offset = p_t2t->work_offset;
1173 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1174 while (index < T2T_BLOCK_SIZE &&
1175 p_t2t->work_offset <
1176 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1177 if (rw_t2t_is_lock_res_byte(
1178 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1179 write_block[index] =
1180 p_t2t
1181 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1182 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001183 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001184 index++;
1185 }
1186 if (p_t2t->work_offset == initial_offset) {
1187 index = 0;
1188 block++;
1189 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001190 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001191 } else {
1192 /* Complete writting Length field and then write ndef message */
1193 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1194 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1195 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1196 if (new_lengthfield_len == 3) {
1197 /* New NDEF is Long NDEF */
1198 if (msg_len == 0) {
1199 length_field[0] = 0x00;
1200 length_field[1] = 0x00;
1201 length_field[2] = 0x00;
1202 } else {
1203 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1204 length_field[1] = (uint8_t)(msg_len >> 8);
1205 length_field[2] = (uint8_t)(msg_len);
1206 }
1207 } else {
1208 /* New NDEF is short NDEF */
1209 length_field[0] = (uint8_t)(msg_len);
1210 }
1211 initial_offset = p_t2t->work_offset;
1212 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1213 /* Update length field */
1214 while (index < T2T_BLOCK_SIZE &&
1215 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1216 if (rw_t2t_is_lock_res_byte(
1217 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1218 write_block[index] = length_field[p_t2t->work_offset];
1219 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001220 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001221 index++;
1222 if (p_t2t->work_offset == new_lengthfield_len) {
1223 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001224 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001225 }
1226 /* Update ndef message field */
1227 while (index < T2T_BLOCK_SIZE &&
1228 p_t2t->work_offset <
1229 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1230 if (rw_t2t_is_lock_res_byte(
1231 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1232 write_block[index] =
1233 p_t2t
1234 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1235 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001236 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001237 index++;
1238 }
1239 if (p_t2t->work_offset == initial_offset) {
1240 index = 0;
1241 block++;
1242 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001243 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001244 }
1245 if (p_t2t->work_offset == initial_offset) {
1246 status = NFC_STATUS_FAILED;
1247 } else {
1248 rw_t2t_update_cb(block, write_block, b_update_len);
1249 /* Write the NDEF Block */
1250 status = rw_t2t_write(block, write_block);
1251 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001252
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001253 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001254}
1255
1256/*******************************************************************************
1257**
1258** Function rw_t2t_update_cb
1259**
1260** Description This function can be called to write an NDEF message block
1261**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001262** Returns NCI_STATUS_OK, if write was started.
1263** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001264**
1265*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001266static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
1267 bool b_update_len) {
1268 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1269 uint8_t new_lengthfield_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001270
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001271 /* Write NDEF Message */
1272 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1273 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1274 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001275
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001276 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1277 /* Update ndef first block if the 'block' points to ndef first block */
1278 memcpy(p_t2t->ndef_first_block, p_write_block, T2T_BLOCK_SIZE);
1279 }
1280 if (p_t2t->terminator_byte_index / T2T_BLOCK_SIZE == block) {
1281 /* Update terminator block if the 'block' points to terminator tlv block */
1282 memcpy(p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1283 }
1284 if (b_update_len == false) {
1285 if (block == p_t2t->ndef_last_block_num) {
1286 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1287 p_t2t->work_offset = 0;
1288 /* Update ndef final block if the 'block' points to ndef final block */
1289 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
1290 } else {
1291 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001292 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001293 } else {
1294 if (block == p_t2t->ndef_last_block_num) {
1295 /* Update the backup of Ndef final block TLV block */
1296 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001297 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001298
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001299 if (p_t2t->work_offset >= new_lengthfield_len) {
1300 if (p_t2t->terminator_byte_index != 0) {
1301 /* Add Terminator TLV as part of NDEF Write operation */
1302 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1303 } else {
1304 /* Skip adding Terminator TLV */
1305 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1306 }
1307 } else {
1308 /* Part of NDEF Message Len should be added in the next block */
1309 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001310 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001311 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001312}
1313
1314/*******************************************************************************
1315**
1316** Function rw_t2t_get_ndef_flags
1317**
1318** Description Prepare NDEF Flags
1319**
1320** Returns NDEF Flag value
1321**
1322*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001323static uint8_t rw_t2t_get_ndef_flags(void) {
1324 uint8_t flags = 0;
1325 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1326 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001327
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001328 flags |= RW_NDEF_FL_SUPPORTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001329
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001330 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) ||
1331 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1332 flags |= RW_NDEF_FL_FORMATABLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001333
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001334 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1335 flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001336
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001337 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1338 (p_ret->b_otp)) {
1339 /* Set otp flag */
1340 flags |= RW_NDEF_FL_OTP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001341
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001342 /* Set Read only flag if otp tag already has NDEF Message */
1343 if (p_t2t->ndef_msg_len) flags |= RW_NDEF_FL_READ_ONLY;
1344 }
1345 return flags;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001346}
1347
1348/*******************************************************************************
1349**
1350** Function rw_t2t_get_ndef_max_size
1351**
1352** Description Calculate maximum size of NDEF message that can be written
1353** on to the tag
1354**
1355** Returns Maximum size of NDEF Message
1356**
1357*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001358static uint16_t rw_t2t_get_ndef_max_size(void) {
1359 uint16_t offset;
1360 uint8_t xx;
1361 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1362 uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
1363 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
1364 p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001365
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001366 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1367 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001368
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001369 offset = p_t2t->ndef_msg_offset;
1370 p_t2t->max_ndef_msg_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001371
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001372 if ((tag_size < T2T_STATIC_SIZE) ||
1373 (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
1374 ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
1375 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
1376 /* Tag not formated, assume static tag */
1377 p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
1378 T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001379 return p_t2t->max_ndef_msg_len;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001380 }
1381
1382 /* Starting from NDEF Message offset find the first locked data byte */
1383 while (offset < tag_size) {
1384 if (rw_t2t_is_lock_res_byte((uint16_t)offset) == false) {
1385 if (rw_t2t_is_read_only_byte((uint16_t)offset) == true) break;
1386 p_t2t->max_ndef_msg_len++;
1387 }
1388 offset++;
1389 }
1390 /* NDEF Length field length changes based on NDEF size */
1391 if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
1392 ((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
1393 T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
1394 p_t2t->max_ndef_msg_len -=
1395 (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1396 ? 1
1397 : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1398 }
1399 return p_t2t->max_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001400}
1401
1402/*******************************************************************************
1403**
1404** Function rw_t2t_add_terminator_tlv
1405**
1406** Description This function will add terminator TLV after NDEF Message
1407**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001408** Returns NCI_STATUS_OK, if write was started.
1409** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001410**
1411*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001412tNFC_STATUS rw_t2t_add_terminator_tlv(void) {
1413 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1414 tNFC_STATUS status;
1415 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001416
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001417 /* Add Terminator TLV after NDEF Message */
1418 p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
1419 TAG_TERMINATOR_TLV;
1420 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001421
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001422 block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
1423 status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001424
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001425 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001426}
1427
1428/*******************************************************************************
1429**
1430** Function rw_t2t_handle_ndef_read_rsp
1431**
1432** Description This function handles reading an NDEF message.
1433**
1434** Returns none
1435**
1436*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001437static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data) {
1438 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1439 tRW_READ_DATA evt_data;
1440 uint16_t len;
1441 uint16_t offset;
1442 bool failed = false;
1443 bool done = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001444
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001445 /* On the first read, adjust for any partial block offset */
1446 offset = 0;
1447 len = T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001448
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001449 if (p_t2t->work_offset == 0) {
1450 /* The Ndef Message offset may be present in the read 16 bytes */
1451 offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1452 }
1453
1454 /* Skip all reserved and lock bytes */
1455 while ((offset < len) && (p_t2t->work_offset < p_t2t->ndef_msg_len))
1456
1457 {
1458 if (rw_t2t_is_lock_res_byte(
1459 (uint16_t)(offset + p_t2t->block_read * T2T_BLOCK_LEN)) == false) {
1460 /* Collect the NDEF Message */
1461 p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1462 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001463 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001464 offset++;
1465 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001466
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001467 if (p_t2t->work_offset >= p_t2t->ndef_msg_len) {
1468 done = true;
1469 p_t2t->ndef_status = T2T_NDEF_READ;
1470 } else {
1471 /* Read next 4 blocks */
1472 if (rw_t2t_read((uint16_t)(p_t2t->block_read + T2T_READ_BLOCKS)) !=
1473 NFC_STATUS_OK)
1474 failed = true;
1475 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001476
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001477 if (failed || done) {
1478 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1479 evt_data.p_data = NULL;
1480 rw_t2t_handle_op_complete();
1481 (*rw_cb.p_cback)(RW_T2T_NDEF_READ_EVT, (tRW_DATA*)&evt_data);
1482 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001483}
1484
1485/*******************************************************************************
1486**
1487** Function rw_t2t_handle_ndef_write_rsp
1488**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001489** Description Handle response received to reading (or part of) NDEF
1490** message.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001491**
1492** Returns none
1493**
1494*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001495static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data) {
1496 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1497 tRW_READ_DATA evt_data;
1498 bool failed = false;
1499 bool done = false;
1500 uint16_t block;
1501 uint8_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001502
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001503 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001504 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1505
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001506 /* Backup the read NDEF first block */
1507 memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1508 /* Read ndef final block */
1509 if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
1510 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001511
1512 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1513
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001514 offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
1515 T2T_BLOCK_SIZE;
1516 /* Backup the read NDEF final block */
1517 memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1518 if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
1519 p_t2t->ndef_last_block_num) {
1520 /* If Terminator TLV will reside on the NDEF Final block */
1521 memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
1522 T2T_BLOCK_LEN);
1523 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1524 failed = true;
1525 } else if (p_t2t->terminator_byte_index != 0) {
1526 /* If there is space for Terminator TLV and if it will reside outside
1527 * NDEF Final block */
1528 if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
1529 } else {
1530 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1531 failed = true;
1532 }
1533 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001534
1535 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1536
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001537 offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
1538 p_t2t->block_read) *
1539 T2T_BLOCK_SIZE);
1540 /* Backup the read Terminator TLV block */
1541 memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001542
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001543 /* Write the first block for new NDEF Message */
1544 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1545 failed = true;
1546 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001547
1548 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1549
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001550 offset = (uint8_t)(p_t2t->ndef_read_block_num - p_t2t->block_read) *
1551 T2T_BLOCK_SIZE;
1552 /* Backup read block */
1553 memcpy(p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001554
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001555 /* Update the block with new NDEF Message */
1556 if (rw_t2t_write_ndef_next_block(p_t2t->ndef_read_block_num, 0x0000,
1557 false) != NFC_STATUS_OK)
1558 failed = true;
1559 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001560
1561 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1562 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001563 if (rw_t2t_is_read_before_write_block(
1564 (uint16_t)(p_t2t->block_written + 1), &block) == true) {
1565 p_t2t->ndef_read_block_num = block;
1566 /* If only part of the block is going to be updated read the block to
1567 retain previous data for
1568 unchanged part of the block */
1569 if (rw_t2t_read_ndef_next_block(block) != NFC_STATUS_OK) failed = true;
1570 } else {
1571 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK) {
1572 /* Directly write the block with new NDEF contents as whole block is
1573 * going to be updated */
1574 if (rw_t2t_write_ndef_next_block(block, p_t2t->new_ndef_msg_len,
1575 true) != NFC_STATUS_OK)
1576 failed = true;
1577 } else {
1578 /* Directly write the block with new NDEF contents as whole block is
1579 * going to be updated */
1580 if (rw_t2t_write_ndef_next_block(block, 0x0000, false) !=
1581 NFC_STATUS_OK)
1582 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001583 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001584 }
1585 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001586
1587 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001588 /* Write the next block for new NDEF Message */
1589 p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1590 if (rw_t2t_is_read_before_write_block((uint16_t)(p_t2t->ndef_write_block),
1591 &block) == true) {
1592 /* If only part of the block is going to be updated read the block to
1593 retain previous data for
1594 part of the block thats not going to be changed */
1595 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1596 if (rw_t2t_read(block) != NFC_STATUS_OK) failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001597
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001598 } else {
1599 /* Update NDEF Message Length in the Tag */
1600 if (rw_t2t_write_ndef_first_block(p_t2t->new_ndef_msg_len, true) !=
1601 NFC_STATUS_OK)
1602 failed = true;
1603 }
1604 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001605
1606 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001607 /* Backup read block */
1608 memcpy(p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001609
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001610 /* Update the block with new NDEF Message */
1611 if (rw_t2t_write_ndef_next_block(p_t2t->block_read,
1612 p_t2t->new_ndef_msg_len,
1613 true) == NFC_STATUS_OK)
1614 p_t2t->ndef_write_block = p_t2t->block_read + 1;
1615 else
1616 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001617
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001618 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001619
1620 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001621 if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
1622 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001623
1624 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001625 done = true;
1626 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001627
1628 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001629 break;
1630 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001631
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001632 if (failed || done) {
1633 evt_data.p_data = NULL;
1634 /* NDEF WRITE Operation is done, inform up the stack */
1635 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1636 if (done) {
1637 if ((p_t2t->ndef_msg_len >= 0x00FF) &&
1638 (p_t2t->new_ndef_msg_len < 0x00FF)) {
1639 p_t2t->ndef_msg_offset -= 2;
1640 } else if ((p_t2t->new_ndef_msg_len >= 0x00FF) &&
1641 (p_t2t->ndef_msg_len < 0x00FF)) {
1642 p_t2t->ndef_msg_offset += 2;
1643 }
1644 p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001645 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001646 rw_t2t_handle_op_complete();
1647 (*rw_cb.p_cback)(RW_T2T_NDEF_WRITE_EVT, (tRW_DATA*)&evt_data);
1648 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001649}
1650
1651/*******************************************************************************
1652**
1653** Function rw_t2t_get_tag_size
1654**
1655** Description This function calculates tag data area size from data read
1656** from block with version number
1657**
1658** Returns TMS of the tag
1659**
1660*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001661static uint8_t rw_t2t_get_tag_size(uint8_t* p_data) {
1662 uint16_t LchunkSize = 0;
1663 uint16_t Num_LChuncks = 0;
1664 uint16_t tms = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001665
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001666 LchunkSize = (uint16_t)p_data[2] << 8 | p_data[3];
1667 Num_LChuncks = (uint16_t)p_data[4] << 8 | p_data[5];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001668
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001669 tms = (uint16_t)(LchunkSize * Num_LChuncks);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001670
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001671 tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001672
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001673 tms /= 0x08;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001674
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001675 return (uint8_t)tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001676}
1677
1678/*******************************************************************************
1679**
1680** Function rw_t2t_handle_config_tag_readonly
1681**
1682** Description This function handles configure type 2 tag as read only
1683**
1684** Returns none
1685**
1686*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001687static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data) {
1688 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1689 tNFC_STATUS status = NFC_STATUS_FAILED;
1690 bool b_notify = false;
1691 uint8_t write_block[T2T_BLOCK_SIZE];
1692 tRW_DATA evt;
1693 bool b_pending = false;
1694 uint8_t read_lock = 0;
1695 uint8_t num_locks = 0;
1696 uint16_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001697
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001698 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001699 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1700
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001701 /* First soft lock the tag */
1702 rw_t2t_soft_lock_tag();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001703
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001704 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001705
1706 case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1707
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001708 /* Successfully soft locked! Update Tag header for future reference */
1709 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1710 if (!p_t2t->b_hard_lock) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001711 /* Tag configuration complete */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001712 status = NFC_STATUS_OK;
Ruchi Kandoi4a179642017-01-04 10:04:48 -08001713 b_notify = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001714 break;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001715 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001716
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001717 /* Coverity: [FALSE-POSITIVE error] intended fall through */
1718 /* Missing break statement between cases in switch statement */
1719 /* fall through */
1720 case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001721
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001722 num_locks = 0;
1723
1724 while (num_locks < p_t2t->num_lockbytes) {
1725 if (p_t2t->lockbyte[num_locks].lock_status ==
1726 RW_T2T_LOCK_UPDATE_INITIATED) {
1727 /* Update control block as one or more dynamic lock byte (s) are set
1728 */
1729 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1730 }
1731 if (!b_pending &&
1732 p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
1733 /* One or more dynamic lock bits are not set */
1734 b_pending = true;
1735 read_lock = num_locks;
1736 }
1737 num_locks++;
1738 }
1739
1740 if (b_pending) {
1741 /* Read the block where dynamic lock bits are present to avoid writing
1742 * to NDEF bytes in the same block */
1743 offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
1744 p_t2t->lockbyte[read_lock].byte_index;
1745 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1746 status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
1747 } else {
1748 /* Now set Static lock bits as no more dynamic lock bits to set */
1749
1750 /* Copy the internal bytes */
1751 memcpy(write_block,
1752 &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
1753 T2T_INTERNAL_BYTES_LEN);
1754 /* Set all Static lock bits */
1755 write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1756 write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1757 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1758 status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1759 }
1760 break;
1761
1762 case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1763 /* Now set the dynamic lock bits present in the block read now */
1764 status = rw_t2t_set_dynamic_lock_bits(p_data);
1765 break;
1766
1767 case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1768 /* Tag configuration complete */
1769 status = NFC_STATUS_OK;
1770 b_notify = true;
1771 break;
1772 }
1773
1774 if (status != NFC_STATUS_OK || b_notify) {
1775 /* Notify upper layer the result of Configuring Tag as Read only */
1776 evt.status = status;
1777 rw_t2t_handle_op_complete();
1778 (*rw_cb.p_cback)(RW_T2T_SET_TAG_RO_EVT, (tRW_DATA*)&evt);
1779 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001780}
1781
1782/*******************************************************************************
1783**
1784** Function rw_t2t_handle_format_tag_rsp
1785**
1786** Description This function handles formating a type 2 tag
1787**
1788** Returns none
1789**
1790*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001791static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data) {
1792 tRW_DATA evt;
1793 uint8_t* p;
1794 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1795 tNFC_STATUS status = NFC_STATUS_FAILED;
1796 uint16_t version_no;
1797 const tT2T_INIT_TAG* p_ret;
1798 uint8_t tms;
1799 uint8_t next_block = T2T_FIRST_DATA_BLOCK + 1;
1800 uint16_t addr, locked_area;
1801 bool b_notify = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001802
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001803 p = p_t2t->ndef_final_block;
1804 UINT8_TO_BE_STREAM(p, p_t2t->tlv_value[2]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001805
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001806 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001807 case RW_T2T_SUBSTATE_WAIT_READ_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001808 /* Start format operation */
1809 status = rw_t2t_format_tag();
1810 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001811
1812 case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1813
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001814 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1815 p_t2t->b_read_data = true;
1816 version_no = (uint16_t)p_data[0] << 8 | p_data[1];
1817 if ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) !=
1818 NULL) {
1819 /* Valid Version Number */
1820 if (p_ret->b_calc_cc) /* Calculate tag size from Version Information */
1821 tms = rw_t2t_get_tag_size(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001822
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001823 else
1824 /* Tag size from Look up table */
1825 tms = p_ret->tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001826
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001827 /* Set CC with the Tag size from look up table or from calculated value
1828 */
1829 status = rw_t2t_set_cc(tms);
1830 }
1831 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001832
1833 case RW_T2T_SUBSTATE_WAIT_SET_CC:
1834
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001835 version_no = (uint16_t)p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1836 if ((version_no == 0) ||
1837 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) ==
1838 NULL) ||
1839 (!p_ret->b_multi_version) || (!p_ret->b_calc_cc)) {
1840 /* Currently Formating a non blank tag or a blank tag with manufacturer
1841 * has only one variant of tag. Set Null NDEF TLV and complete Format
1842 * Operation */
1843 next_block = T2T_FIRST_DATA_BLOCK;
1844 p = p_t2t->ndef_final_block;
1845 } else {
1846 addr = (uint16_t)(
1847 ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1848 ((uint16_t)p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) +
1849 T2T_STATIC_SIZE);
1850 locked_area = ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1851 ((uint16_t)p_t2t->tag_data[6]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001852
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001853 if ((status =
1854 rw_t2t_set_lock_tlv(addr, p_t2t->tag_data[7], locked_area)) ==
1855 NFC_STATUS_REJECTED) {
1856 /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format
1857 * Operation */
1858 next_block = T2T_FIRST_DATA_BLOCK;
1859 p = p_t2t->ndef_final_block;
1860 } else
1861 break;
1862 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001863
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001864 /* falls through */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001865 case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
1866
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001867 /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
1868 UINT8_TO_BE_STREAM(p, TAG_NDEF_TLV);
1869 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001870
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001871 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1872 (!p_ret->b_otp)) {
1873 UINT8_TO_BE_STREAM(p, TAG_TERMINATOR_TLV);
1874 } else
1875 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001876
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001877 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
1878 /* send WRITE-E8 command */
1879 if ((status = rw_t2t_write(next_block, p_t2t->ndef_final_block)) ==
1880 NFC_STATUS_OK)
1881 p_t2t->b_read_data = false;
1882 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001883
1884 case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001885 /* Tag Formated successfully */
1886 status = NFC_STATUS_OK;
1887 b_notify = true;
1888 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001889
1890 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001891 break;
1892 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001893
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001894 if (status != NFC_STATUS_OK || b_notify) {
1895 /* Notify upper layer the result of Format op */
1896 evt.status = status;
1897 rw_t2t_handle_op_complete();
1898 (*rw_cb.p_cback)(RW_T2T_FORMAT_CPLT_EVT, (tRW_DATA*)&evt);
1899 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001900}
1901
1902/*******************************************************************************
1903**
1904** Function rw_t2t_update_attributes
1905**
1906** Description This function will update attribute for the current segment
1907** based on lock and reserved bytes
1908**
1909** Returns None
1910**
1911*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001912static void rw_t2t_update_attributes(void) {
1913 uint8_t count = 0;
1914 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1915 uint16_t lower_offset;
1916 uint16_t upper_offset;
1917 uint16_t offset;
1918 uint8_t num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001919
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001920 /* Prepare attr for the current segment */
1921 memset(p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001922
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001923 /* calculate offset where the current segment starts in the tag */
1924 lower_offset = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
1925 /* calculate offset where the current segment ends in the tag */
1926 upper_offset = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001927
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001928 /* check offset of lock bytes in the tag and update p_t2t->attr
1929 * for every lock byte that is present in the current segment */
1930 count = 0;
1931 while (count < p_t2t->num_lockbytes) {
1932 offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset +
1933 p_t2t->lockbyte[count].byte_index;
1934 if (offset >= lower_offset && offset < upper_offset) {
1935 /* Calculate offset in the current segment as p_t2t->attr is prepared for
1936 * one segment only */
1937 offset %= RW_T2T_SEGMENT_BYTES;
1938 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1939 * lock/reserved byte or not
1940 * So, each array element in p_t2t->attr covers two blocks in the tag as
1941 * T2 block size is 4 and array element size is 8
1942 * Set the corresponding bit in attr to indicate - reserved byte */
1943 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1944 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001945 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001946 count++;
1947 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001948
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001949 /* Search reserved bytes identified by all memory tlvs present in the tag */
1950 count = 0;
1951 while (count < p_t2t->num_mem_tlvs) {
1952 /* check the offset of reserved bytes in the tag and update p_t2t->attr
1953 * for every reserved byte that is present in the current segment */
1954 num_bytes = 0;
1955 while (num_bytes < p_t2t->mem_tlv[count].num_bytes) {
1956 offset = p_t2t->mem_tlv[count].offset + num_bytes;
1957 if (offset >= lower_offset && offset < upper_offset) {
1958 /* Let offset represents offset in the current segment as p_t2t->attr is
1959 * prepared for one segment only */
1960 offset %= RW_T2T_SEGMENT_BYTES;
1961 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1962 * lock/reserved byte or not
1963 * So, each array element in p_t2t->attr covers two blocks in the tag as
1964 * T2 block size is 4 and array element size is 8
1965 * Set the corresponding bit in attr to indicate - reserved byte */
1966 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1967 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
1968 }
1969 num_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001970 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001971 count++;
1972 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001973}
1974
1975/*******************************************************************************
1976**
1977** Function rw_t2t_get_lock_bits_for_segment
1978**
1979** Description This function returns the offset of lock bits associated for
1980** the specified segment
1981**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001982** Parameters: segment: The segment number to which lock bits are
1983** associated
1984** p_start_byte: The offset of lock byte that contains the
1985** first lock bit for the segment
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001986** p_start_bit: The offset of the lock bit in the lock byte
1987**
1988** p_end_byte: The offset of the last bit associcated to the
1989** segment
1990**
1991** Returns Total number of lock bits assigned to the specified segment
1992**
1993*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001994static uint8_t rw_t2t_get_lock_bits_for_segment(uint8_t segment,
1995 uint8_t* p_start_byte,
1996 uint8_t* p_start_bit,
1997 uint8_t* p_end_byte) {
1998 uint8_t total_bits = 0;
1999 uint16_t byte_count = 0;
2000 uint16_t lower_offset, upper_offset;
2001 uint8_t num_dynamic_locks = 0;
2002 uint8_t bit_count = 0;
2003 uint8_t bytes_locked_per_bit;
2004 uint8_t num_bits;
2005 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2006 bool b_all_bits_are_locks = true;
2007 uint16_t tag_size;
2008 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002009
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002010 tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
2011 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002012
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002013 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2014 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002015
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002016 lower_offset = segment * RW_T2T_SEGMENT_BYTES;
2017 if (segment == 0) {
2018 lower_offset += T2T_STATIC_SIZE;
2019 }
2020 upper_offset = (segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002021
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002022 byte_count = T2T_STATIC_SIZE;
2023 if (tag_size < upper_offset) {
2024 upper_offset = tag_size;
2025 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002026
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002027 *p_start_byte = num_dynamic_locks;
2028 *p_start_bit = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002029
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002030 while ((byte_count <= lower_offset) &&
2031 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2032 bytes_locked_per_bit =
2033 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2034 .bytes_locked_per_bit;
2035 /* Number of bits in the current lock byte */
2036 b_all_bits_are_locks =
2037 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2038 TAG_BITS_PER_BYTE <=
2039 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2040 .num_bits);
2041 num_bits =
2042 b_all_bits_are_locks
2043 ? TAG_BITS_PER_BYTE
2044 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2045 .num_bits %
2046 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002047
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002048 if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset) {
2049 /* Skip this lock byte as it covers different segment */
2050 byte_count += bytes_locked_per_bit * num_bits;
2051 num_dynamic_locks++;
2052 } else {
2053 bit_count = 0;
2054 while (bit_count < num_bits) {
2055 byte_count += bytes_locked_per_bit;
2056 if (byte_count > lower_offset) {
2057 /* First lock bit that is used to lock this segment */
2058 *p_start_byte = num_dynamic_locks;
2059 *p_end_byte = num_dynamic_locks;
2060 *p_start_bit = bit_count;
2061 bit_count++;
2062 total_bits = 1;
2063 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002064 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002065 bit_count++;
2066 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002067 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002068 }
2069 if (num_dynamic_locks == p_t2t->num_lockbytes) {
2070 return 0;
2071 }
2072 while ((byte_count < upper_offset) &&
2073 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2074 bytes_locked_per_bit =
2075 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2076 .bytes_locked_per_bit;
2077 /* Number of bits in the current lock byte */
2078 b_all_bits_are_locks =
2079 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2080 TAG_BITS_PER_BYTE <=
2081 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2082 .num_bits);
2083 num_bits =
2084 b_all_bits_are_locks
2085 ? TAG_BITS_PER_BYTE
2086 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2087 .num_bits %
2088 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002089
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002090 if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count <
2091 upper_offset) {
2092 /* Collect all lock bits that covers the current segment */
2093 byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2094 total_bits += num_bits - bit_count;
2095 bit_count = 0;
2096 *p_end_byte = num_dynamic_locks;
2097 num_dynamic_locks++;
2098 } else {
2099 /* The last lock byte that covers the current segment */
2100 bit_count = 0;
2101 while (bit_count < num_bits) {
2102 /* The last lock bit that is used to lock this segment */
2103 byte_count += bytes_locked_per_bit;
2104 if (byte_count >= upper_offset) {
2105 *p_end_byte = num_dynamic_locks;
2106 total_bits += (bit_count + 1);
2107 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002108 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002109 bit_count++;
2110 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002111 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002112 }
2113 return total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002114}
2115
2116/*******************************************************************************
2117**
2118** Function rw_t2t_update_lock_attributes
2119**
2120** Description This function will check if the tag index passed as
2121** argument is a locked byte and return TRUE or FALSE
2122**
2123** Parameters: index, the index of the byte in the tag
2124**
2125**
2126** Returns TRUE, if the specified index in the tag is a locked or
2127** reserved or otp byte
2128** FALSE, otherwise
2129**
2130*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002131static void rw_t2t_update_lock_attributes(void) {
2132 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2133 uint8_t xx = 0;
2134 uint8_t num_static_lock_bytes = 0;
2135 uint8_t num_dyn_lock_bytes = 0;
2136 uint8_t bits_covered = 0;
2137 uint8_t bytes_covered = 0;
2138 uint8_t block_count = 0;
2139 bool b_all_bits_are_locks = true;
2140 uint8_t bytes_locked_per_lock_bit;
2141 uint8_t start_lock_byte;
2142 uint8_t start_lock_bit;
2143 uint8_t end_lock_byte;
2144 uint8_t num_lock_bits;
2145 uint8_t total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002146
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002147 /* Prepare lock_attr for the current segment */
2148 memset(p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002149
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002150 block_count = 0;
2151 if (p_t2t->segment == 0) {
2152 /* Update lock_attributes based on static lock bytes */
2153 xx = 0;
2154 num_static_lock_bytes = 0;
2155 block_count = 0;
2156 num_lock_bits =
2157 TAG_BITS_PER_BYTE - 1; /* the inner while loop increases xx by 2. need
2158 (-1) to avoid coverity overrun error */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002159
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002160 while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES) {
2161 /* Update lock attribute based on 2 static locks */
2162 while (xx < num_lock_bits) {
2163 p_t2t->lock_attr[block_count] = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002164
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002165 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2166 rw_t2t_mask_bits[xx++]) {
2167 /* If the bit is set then 1 block is locked */
2168 p_t2t->lock_attr[block_count] = 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002169 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002170
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002171 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2172 rw_t2t_mask_bits[xx++]) {
2173 /* If the bit is set then 1 block is locked */
2174 p_t2t->lock_attr[block_count] |= 0xF0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002175 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002176 block_count++;
2177 }
2178 num_static_lock_bytes++;
2179 xx = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002180 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002181 /* UID is always locked, irrespective of the lock value */
2182 p_t2t->lock_attr[0x00] = 0xFF;
2183 }
2184
2185 /* Get lock bits applicable for the current segment */
2186 if ((total_bits = rw_t2t_get_lock_bits_for_segment(
2187 p_t2t->segment, &start_lock_byte, &start_lock_bit,
2188 &end_lock_byte)) != 0) {
2189 /* update lock_attributes based on current segment using dynamic lock bytes
2190 */
2191 xx = start_lock_bit;
2192 num_dyn_lock_bytes = start_lock_byte;
2193 bits_covered = 0;
2194 bytes_covered = 0;
2195 num_lock_bits = TAG_BITS_PER_BYTE;
2196 p_t2t->lock_attr[block_count] = 0;
2197
2198 while (num_dyn_lock_bytes <= end_lock_byte) {
2199 bytes_locked_per_lock_bit =
2200 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2201 .bytes_locked_per_bit;
2202 /* Find number of bits in the byte are lock bits */
2203 b_all_bits_are_locks =
2204 ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) *
2205 TAG_BITS_PER_BYTE <=
2206 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2207 .num_bits);
2208 num_lock_bits =
2209 b_all_bits_are_locks
2210 ? TAG_BITS_PER_BYTE
2211 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2212 .num_bits %
2213 TAG_BITS_PER_BYTE;
2214
2215 while (xx < num_lock_bits) {
2216 bytes_covered = 0;
2217 while (bytes_covered < bytes_locked_per_lock_bit) {
2218 if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte &
2219 rw_t2t_mask_bits[xx]) {
2220 /* If the bit is set then it is locked */
2221 p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
2222 }
2223 bytes_covered++;
2224 bits_covered++;
2225 if (bits_covered == TAG_BITS_PER_BYTE) {
2226 /* Move to next 8 bytes */
2227 bits_covered = 0;
2228 block_count++;
2229 /* Assume unlocked before updating using locks */
2230 if (block_count < RW_T2T_SEGMENT_SIZE)
2231 p_t2t->lock_attr[block_count] = 0;
2232 }
2233 }
2234 xx++;
2235 }
2236 num_dyn_lock_bytes++;
2237 xx = 0;
2238 }
2239 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002240}
2241
2242/*******************************************************************************
2243**
2244** Function rw_t2t_is_lock_res_byte
2245**
2246** Description This function will check if the tag index passed as
2247** argument is a lock or reserved or otp byte and return
2248** TRUE or FALSE
2249**
2250** Parameters: index, the index of the byte in the tag
2251**
2252**
2253** Returns TRUE, if the specified index in the tag is a locked or
2254** reserved or otp byte
2255** FALSE, otherwise
2256**
2257*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002258static bool rw_t2t_is_lock_res_byte(uint16_t index) {
2259 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002260
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002261 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002262
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002263 if (p_t2t->attr_seg != p_t2t->segment) {
2264 /* Update attributes for the current segment */
2265 rw_t2t_update_attributes();
2266 p_t2t->attr_seg = p_t2t->segment;
2267 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002268
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002269 index = index % RW_T2T_SEGMENT_BYTES;
2270 /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a
2271 * lock/reserved byte or not
2272 * So, each array element in p_t2t->attr covers two blocks in the tag as T2
2273 * block size is 4 and array element size is 8
2274 * Find the block and offset for the index (passed as argument) and Check if
2275 * the offset bit in the
2276 * p_t2t->attr[block/2] is set or not. If the bit is set then it is a
2277 * lock/reserved byte, otherwise not */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002278
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002279 return ((p_t2t->attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0) ? false
2280 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002281}
2282
2283/*******************************************************************************
2284**
2285** Function rw_t2t_is_read_only_byte
2286**
2287** Description This function will check if the tag index passed as
2288** argument is a locked and return
2289** TRUE or FALSE
2290**
2291** Parameters: index, the index of the byte in the tag
2292**
2293**
2294** Returns TRUE, if the specified index in the tag is a locked or
2295** reserved or otp byte
2296** FALSE, otherwise
2297**
2298*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002299static bool rw_t2t_is_read_only_byte(uint16_t index) {
2300 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002301
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002302 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002303
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002304 if (p_t2t->lock_attr_seg != p_t2t->segment) {
2305 /* Update lock attributes for the current segment */
2306 rw_t2t_update_lock_attributes();
2307 p_t2t->lock_attr_seg = p_t2t->segment;
2308 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002309
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002310 index = index % RW_T2T_SEGMENT_BYTES;
2311 /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a
2312 * read only byte or read write byte
2313 * So, each array element in p_t2t->lock_attr covers two blocks of the tag as
2314 * T2 block size is 4 and array element size is 8
2315 * Find the block and offset for the index (passed as argument) and Check if
2316 * the offset bit in
2317 * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a
2318 * read only byte, otherwise read write byte */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002319
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002320 return ((p_t2t->lock_attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0)
2321 ? false
2322 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002323}
2324
2325/*******************************************************************************
2326**
2327** Function rw_t2t_set_dynamic_lock_bits
2328**
2329** Description This function will set dynamic lock bits as part of
2330** configuring tag as read only
2331**
2332** Returns
2333** NFC_STATUS_OK, Command sent to set dynamic lock bits
2334** NFC_STATUS_FAILED: otherwise
2335**
2336*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002337tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data) {
2338 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2339 uint8_t write_block[T2T_BLOCK_SIZE];
2340 uint16_t offset;
2341 uint16_t next_offset;
2342 uint8_t num_bits;
2343 uint8_t next_num_bits;
2344 tNFC_STATUS status = NFC_STATUS_FAILED;
2345 uint8_t num_locks;
2346 uint8_t lock_count;
2347 bool b_all_bits_are_locks = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002348
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002349 num_locks = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002350
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002351 memcpy(write_block, p_data, T2T_BLOCK_SIZE);
2352 while (num_locks < p_t2t->num_lockbytes) {
2353 if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
2354 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
2355 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002356
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002357 /* Check if all bits are lock bits in the byte */
2358 b_all_bits_are_locks =
2359 ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <=
2360 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2361 num_bits =
2362 b_all_bits_are_locks
2363 ? TAG_BITS_PER_BYTE
2364 : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits %
2365 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002366
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002367 write_block[(uint8_t)(offset % T2T_BLOCK_SIZE)] |=
2368 tags_pow(2, num_bits) - 1;
2369 lock_count = num_locks + 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002370
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002371 /* Set all the lock bits in the block using a sing block write command */
2372 while (lock_count < p_t2t->num_lockbytes) {
2373 next_offset =
2374 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset +
2375 p_t2t->lockbyte[lock_count].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002376
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002377 /* Check if all bits are lock bits in the byte */
2378 b_all_bits_are_locks =
2379 ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <=
2380 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2381 next_num_bits =
2382 b_all_bits_are_locks
2383 ? TAG_BITS_PER_BYTE
2384 : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index]
2385 .num_bits %
2386 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002387
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002388 if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE) {
2389 write_block[(uint8_t)(next_offset % T2T_BLOCK_SIZE)] |=
2390 tags_pow(2, next_num_bits) - 1;
2391 } else
2392 break;
2393 lock_count++;
2394 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002395
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002396 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2397 /* send WRITE command to set dynamic lock bits */
2398 if ((status = rw_t2t_write((uint16_t)(offset / T2T_BLOCK_SIZE),
2399 write_block)) == NFC_STATUS_OK) {
2400 while (lock_count > num_locks) {
2401 /* Set update initiated flag to indicate a write command is sent to
2402 * set dynamic lock bits of the block */
2403 p_t2t->lockbyte[lock_count - 1].lock_status =
2404 RW_T2T_LOCK_UPDATE_INITIATED;
2405 lock_count--;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002406 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002407 } else
2408 status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002409
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002410 break;
2411 }
2412 num_locks++;
2413 }
2414
2415 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002416}
2417
2418/*******************************************************************************
2419**
2420** Function rw_t2t_set_lock_tlv
2421**
2422** Description This function will set lock control tlv on the blank
2423** activated type 2 tag based on values read from version block
2424**
2425** Parameters: TAG data memory size
2426**
2427** Returns
2428** NFC_STATUS_OK, Command sent to set Lock TLV
2429** NFC_STATUS_FAILED: otherwise
2430**
2431*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002432tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
2433 uint16_t locked_area_size) {
2434 tNFC_STATUS status = NFC_STATUS_FAILED;
2435 int8_t PageAddr = 0;
2436 int8_t BytePerPage = 0;
2437 int8_t ByteOffset = 0;
2438 uint8_t a;
2439 uint8_t data_block[T2T_BLOCK_SIZE];
2440 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2441 uint8_t* p;
2442 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002443
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002444 for (xx = 15; xx > 0; xx--) {
2445 a = (uint8_t)(addr / xx);
2446 a += (addr % xx) ? 1 : 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002447
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002448 BytePerPage = (int8_t)tags_log2(a);
2449 ByteOffset = (int8_t)(addr - xx * tags_pow(2, BytePerPage));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002450
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002451 if (ByteOffset < 16) {
2452 PageAddr = xx;
2453 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002454 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002455 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002456
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002457 if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16)) {
2458 memset(data_block, 0, T2T_BLOCK_SIZE);
2459 p = data_block;
2460 UINT8_TO_BE_STREAM(p, T2T_TLV_TYPE_LOCK_CTRL);
2461 UINT8_TO_BE_STREAM(p, T2T_TLEN_LOCK_CTRL_TLV);
2462 UINT8_TO_BE_STREAM(p, (PageAddr << 4 | ByteOffset));
2463 UINT8_TO_BE_STREAM(p, num_dyn_lock_bits);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002464
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002465 p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2466 p_t2t->tlv_value[1] = num_dyn_lock_bits;
2467 p_t2t->tlv_value[2] =
2468 (uint8_t)(BytePerPage << 4 | tags_log2(locked_area_size));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002469
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002470 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002471
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002472 /* send WRITE-E8 command */
2473 if ((status = rw_t2t_write(T2T_FIRST_DATA_BLOCK, data_block)) ==
2474 NFC_STATUS_OK) {
2475 p_t2t->b_read_data = false;
2476 } else
2477 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2478 } else
2479 status = NFC_STATUS_REJECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002480
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002481 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002482}
2483
2484/*******************************************************************************
2485**
2486** Function rw_t2t_set_cc
2487**
2488** Description This function will set Capability Container on the activated
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002489** type 2 tag with default values of CC0, CC1, CC4 and
2490** specified CC3 value
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002491**
2492** Parameters: CC3 value of the tag
2493**
2494** Returns
2495** NFC_STATUS_OK, Command sent to set CC
2496** NFC_STATUS_FAILED: otherwise
2497**
2498*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002499tNFC_STATUS rw_t2t_set_cc(uint8_t tms) {
2500 uint8_t cc_block[T2T_BLOCK_SIZE];
2501 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2502 tNFC_STATUS status = NFC_STATUS_FAILED;
2503 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002504
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002505 memset(cc_block, 0, T2T_BLOCK_SIZE);
2506 memset(p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2507 p = cc_block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002508
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002509 /* Prepare Capability Container */
2510 UINT8_TO_BE_STREAM(p, T2T_CC0_NMN);
2511 UINT8_TO_BE_STREAM(p, T2T_CC1_VNO);
2512 UINT8_TO_BE_STREAM(p, tms);
2513 UINT8_TO_BE_STREAM(p, T2T_CC3_RWA_RW);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002514
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002515 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002516
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002517 /* send WRITE-E8 command */
2518 if ((status = rw_t2t_write(T2T_CC_BLOCK, cc_block)) == NFC_STATUS_OK) {
2519 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2520 p_t2t->b_read_hdr = false;
2521 } else
2522 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002523
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002524 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002525}
2526
2527/*******************************************************************************
2528**
2529** Function rw_t2t_format_tag
2530**
2531** Description This function will format tag based on Manufacturer ID
2532**
2533** Returns
2534** NFC_STATUS_OK, Command sent to format Tag
2535** NFC_STATUS_FAILED: otherwise
2536**
2537*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002538tNFC_STATUS rw_t2t_format_tag(void) {
2539 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2540 const tT2T_INIT_TAG* p_ret;
2541 uint8_t tms;
2542 tNFC_STATUS status = NFC_STATUS_FAILED;
2543 bool b_blank_tag = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002544
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002545 if ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) == NULL) {
2546 RW_TRACE_WARNING1(
2547 "rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the "
2548 "tag!",
2549 p_t2t->tag_hdr[0]);
2550 return (NFC_STATUS_FAILED);
2551 }
2552
2553 if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0) {
2554 /* If OTP tag has valid NDEF Message, cannot format the tag */
2555 if ((p_t2t->ndef_msg_len > 0) && (p_ret->b_otp)) {
2556 RW_TRACE_WARNING0(
2557 "rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2558 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002559 }
2560
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002561 if (((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) &&
2562 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) ||
2563 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) &&
2564 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
2565 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
2566 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
2567 RW_TRACE_WARNING0("rw_t2t_format_tag - Tag not blank to Format!");
2568 return (NFC_STATUS_FAILED);
2569 } else {
2570 tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2571 b_blank_tag = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002572 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002573 } else
2574 tms = p_ret->tms;
2575
2576 memset(p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2577
2578 if (!b_blank_tag || !p_ret->b_multi_version) {
2579 status = rw_t2t_set_cc(tms);
2580 } else if (p_ret->version_block != 0) {
2581 /* If Version number is not read, READ it now */
2582 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2583
2584 if ((status = rw_t2t_read(p_ret->version_block)) == NFC_STATUS_OK)
2585 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002586 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002587 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2588 } else {
2589 /* UID block is the version block */
2590 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2591 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2592 rw_t2t_handle_format_tag_rsp(p_t2t->tag_hdr);
2593 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002594
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002595 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002596}
2597
2598/*******************************************************************************
2599**
2600** Function rw_t2t_soft_lock_tag
2601**
2602** Description This function will soft lock the tag after validating CC.
2603**
2604** Returns
2605** NFC_STATUS_OK, Command sent to soft lock the tag
2606** NFC_STATUS_FAILED: otherwise
2607**
2608*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002609tNFC_STATUS rw_t2t_soft_lock_tag(void) {
2610 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2611 tNFC_STATUS status = NFC_STATUS_FAILED;
2612 uint8_t write_block[T2T_BLOCK_SIZE];
2613 uint8_t num_locks;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002614
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002615 /* If CC block is read and cc3 is soft locked, reject the command */
2616 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO) {
2617 RW_TRACE_ERROR1(
2618 "rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: "
2619 "%u",
2620 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2621 return (NFC_STATUS_FAILED);
2622 }
2623
2624 if (p_t2t->b_hard_lock) {
2625 /* Should have performed NDEF Detection on dynamic memory structure tag,
2626 * before permanently converting to Read only
2627 * Even when no lock control tlv is present, default lock bytes should be
2628 * present */
2629
2630 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) &&
2631 (p_t2t->num_lockbytes == 0)) {
2632 RW_TRACE_ERROR0(
2633 "rw_t2t_soft_lock_tag: Error: Lock TLV not detected! Cannot hard "
2634 "lock the tag");
2635 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002636 }
2637
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002638 /* On dynamic memory structure tag, reset all lock bytes status to 'Not
2639 * Updated' if not in Updated status */
2640 num_locks = 0;
2641 while (num_locks < p_t2t->num_lockbytes) {
2642 if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2643 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2644 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002645 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002646 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002647
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002648 memcpy(write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2649 write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002650
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002651 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2652 /* First Soft lock the tag */
2653 if ((status = rw_t2t_write(T2T_CC_BLOCK, write_block)) == NFC_STATUS_OK) {
2654 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
2655 p_t2t->b_read_hdr = false;
2656 } else {
2657 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2658 }
2659 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002660}
2661
2662/*****************************************************************************
2663**
2664** Function RW_T2tFormatNDef
2665**
2666** Description
2667** Format Tag content
2668**
2669** Returns
2670** NFC_STATUS_OK, Command sent to format Tag
2671** NFC_STATUS_FAILED: otherwise
2672**
2673*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002674tNFC_STATUS RW_T2tFormatNDef(void) {
2675 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2676 tNFC_STATUS status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002677
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002678 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2679 RW_TRACE_WARNING1("RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u",
2680 p_t2t->state);
2681 return (NFC_STATUS_FAILED);
2682 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002683
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002684 if (!p_t2t->b_read_hdr) {
2685 /* If UID is not read, READ it now */
2686 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002687
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002688 if ((status = rw_t2t_read(0)) == NFC_STATUS_OK)
2689 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002690 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002691 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2692 } else {
2693 if ((status = rw_t2t_format_tag()) != NFC_STATUS_OK)
2694 p_t2t->b_read_hdr = false;
2695 }
2696 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002697}
2698
2699/*******************************************************************************
2700**
2701** Function RW_T2tLocateTlv
2702**
2703** Description This function is used to perform TLV detection on a Type 2
2704** tag, and retrieve the tag's TLV attribute information.
2705**
2706** Before using this API, the application must call
2707** RW_SelectTagType to indicate that a Type 2 tag has been
2708** activated.
2709**
2710** Parameters: tlv_type : TLV to detect
2711**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002712** Returns NCI_STATUS_OK, if detection was started. Otherwise, error
2713** status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002714**
2715*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002716tNFC_STATUS RW_T2tLocateTlv(uint8_t tlv_type) {
2717 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2718 tNFC_STATUS status;
2719 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002720
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002721 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2722 RW_TRACE_ERROR1("Error: Type 2 tag not activated or Busy - State: %u",
2723 p_t2t->state);
2724 return (NFC_STATUS_BUSY);
2725 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002726
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002727 if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) &&
2728 (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV)) {
2729 RW_TRACE_API1("RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
2730 return (NFC_STATUS_FAILED);
2731 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002732
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002733 if ((tlv_type == TAG_LOCK_CTRL_TLV) && (p_t2t->b_read_hdr) &&
2734 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)) {
2735 p_t2t->b_read_hdr = false;
2736 RW_TRACE_API1(
2737 "RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x",
2738 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2739 return (NFC_STATUS_FAILED);
2740 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002741
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002742 if ((tlv_type == TAG_NDEF_TLV) && (p_t2t->b_read_hdr) &&
2743 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) {
2744 p_t2t->b_read_hdr = false;
2745 RW_TRACE_WARNING3(
2746 "RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: "
2747 "0x%02x, CC[3]: 0x%02x",
2748 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
2749 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2750 return (NFC_STATUS_FAILED);
2751 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002752
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002753 p_t2t->work_offset = 0;
2754 p_t2t->tlv_detect = tlv_type;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002755
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002756 /* Reset control block variables based on type of tlv to detect */
2757 if (tlv_type == TAG_LOCK_CTRL_TLV) {
2758 p_t2t->num_lockbytes = 0;
2759 p_t2t->num_lock_tlvs = 0;
2760 } else if (tlv_type == TAG_MEM_CTRL_TLV) {
2761 p_t2t->num_mem_tlvs = 0;
2762 } else if (tlv_type == TAG_NDEF_TLV) {
2763 p_t2t->ndef_msg_offset = 0;
2764 p_t2t->num_lockbytes = 0;
2765 p_t2t->num_lock_tlvs = 0;
2766 p_t2t->num_mem_tlvs = 0;
2767 p_t2t->ndef_msg_len = 0;
2768 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
2769 } else {
2770 p_t2t->prop_msg_len = 0;
2771 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002772
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002773 if (!p_t2t->b_read_hdr) {
2774 /* First read CC block */
2775 block = 0;
2776 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2777 } else {
2778 /* Read first data block */
2779 block = T2T_FIRST_DATA_BLOCK;
2780 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2781 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002782
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002783 /* Start reading tag, looking for the specified TLV */
2784 if ((status = rw_t2t_read((uint16_t)block)) == NFC_STATUS_OK) {
2785 p_t2t->state = RW_T2T_STATE_DETECT_TLV;
2786 } else {
2787 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2788 }
2789 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002790}
2791
2792/*******************************************************************************
2793**
2794** Function RW_T2tDetectNDef
2795**
2796** Description This function is used to perform NDEF detection on a Type 2
2797** tag, and retrieve the tag's NDEF attribute information.
2798**
2799** Before using this API, the application must call
2800** RW_SelectTagType to indicate that a Type 2 tag has been
2801** activated.
2802**
2803** Parameters: none
2804**
2805** Returns NCI_STATUS_OK,if detect op started.Otherwise,error status.
2806**
2807*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002808tNFC_STATUS RW_T2tDetectNDef(bool skip_dyn_locks) {
2809 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Evan Chuc95c79c2013-04-12 17:38:09 -04002810
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002811 p_t2t->skip_dyn_locks = skip_dyn_locks;
Evan Chuc95c79c2013-04-12 17:38:09 -04002812
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002813 return RW_T2tLocateTlv(TAG_NDEF_TLV);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002814}
2815
2816/*******************************************************************************
2817**
2818** Function RW_T2tReadNDef
2819**
2820** Description Retrieve NDEF contents from a Type2 tag.
2821**
2822** The RW_T2T_NDEF_READ_EVT event is used to notify the
2823** application after reading the NDEF message.
2824**
2825** Before using this API, the RW_T2tDetectNDef function must
2826** be called to verify that the tag contains NDEF data, and to
2827** retrieve the NDEF attributes.
2828**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002829** Internally, this command will be separated into multiple
2830** Tag2 Read commands (if necessary) - depending on the NDEF
2831** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002832**
2833** Parameters: p_buffer: The buffer into which to read the NDEF message
2834** buf_len: The length of the buffer
2835**
2836** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
2837**
2838*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002839tNFC_STATUS RW_T2tReadNDef(uint8_t* p_buffer, uint16_t buf_len) {
2840 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2841 tNFC_STATUS status = NFC_STATUS_OK;
2842 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002843
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002844 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2845 RW_TRACE_ERROR1("Error: Type 2 tag not activated or Busy - State: %u",
2846 p_t2t->state);
2847 return (NFC_STATUS_FAILED);
2848 }
2849
2850 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
2851 RW_TRACE_ERROR0("RW_T2tReadNDef - Error: NDEF detection not performed yet");
2852 return (NFC_STATUS_FAILED);
2853 }
2854
2855 if (buf_len < p_t2t->ndef_msg_len) {
2856 RW_TRACE_WARNING2(
2857 "RW_T2tReadNDef - buffer size: %u less than NDEF msg sise: %u",
2858 buf_len, p_t2t->ndef_msg_len);
2859 return (NFC_STATUS_FAILED);
2860 }
2861
2862 if (!p_t2t->ndef_msg_len) {
2863 RW_TRACE_WARNING1("RW_T2tReadNDef - NDEF Message length is zero ",
2864 p_t2t->ndef_msg_len);
2865 return (NFC_STATUS_NOT_INITIALIZED);
2866 }
2867
2868 p_t2t->p_ndef_buffer = p_buffer;
2869 p_t2t->work_offset = 0;
2870
2871 block = (uint16_t)(p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
2872 block -= block % T2T_READ_BLOCKS;
2873
2874 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2875
2876 if ((block == T2T_FIRST_DATA_BLOCK) && (p_t2t->b_read_data)) {
2877 p_t2t->state = RW_T2T_STATE_READ_NDEF;
2878 p_t2t->block_read = T2T_FIRST_DATA_BLOCK;
2879 rw_t2t_handle_ndef_read_rsp(p_t2t->tag_data);
2880 } else {
2881 /* Start reading NDEF Message */
2882 if ((status = rw_t2t_read(block)) == NFC_STATUS_OK) {
2883 p_t2t->state = RW_T2T_STATE_READ_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002884 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002885 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002886
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002887 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002888}
2889
2890/*******************************************************************************
2891**
2892** Function RW_T2tWriteNDef
2893**
2894** Description Write NDEF contents to a Type2 tag.
2895**
2896** Before using this API, the RW_T2tDetectNDef
2897** function must be called to verify that the tag contains
2898** NDEF data, and to retrieve the NDEF attributes.
2899**
2900** The RW_T2T_NDEF_WRITE_EVT callback event will be used to
2901** notify the application of the response.
2902**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002903** Internally, this command will be separated into multiple
2904** Tag2 Write commands (if necessary) - depending on the NDEF
2905** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002906**
2907** Parameters: msg_len: The length of the buffer
2908** p_msg: The NDEF message to write
2909**
2910** Returns NCI_STATUS_OK,if write was started. Otherwise, error status
2911**
2912*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002913tNFC_STATUS RW_T2tWriteNDef(uint16_t msg_len, uint8_t* p_msg) {
2914 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2915 uint16_t block;
2916 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002917
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002918 tNFC_STATUS status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002919
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002920 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2921 RW_TRACE_ERROR1("Error: Type 2 tag not activated or Busy - State: %u",
2922 p_t2t->state);
2923 return (NFC_STATUS_FAILED);
2924 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002925
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002926 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
2927 RW_TRACE_ERROR0("RW_T2tWriteNDef - Error: NDEF detection not performed!");
2928 return (NFC_STATUS_FAILED);
2929 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002930
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002931 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) {
2932 RW_TRACE_ERROR1("RW_T2tWriteNDef - Write access not granted - CC3: %u",
2933 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2934 return (NFC_STATUS_REFUSED);
2935 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002936
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002937 /* Check if there is enough memory on the tag */
2938 if (msg_len > p_t2t->max_ndef_msg_len) {
2939 RW_TRACE_ERROR1(
2940 "RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes",
2941 p_t2t->max_ndef_msg_len);
2942 return (NFC_STATUS_FAILED);
2943 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002944
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002945 /* If OTP tag and tag has valid NDEF Message, stop writting new NDEF Message
2946 * as it may corrupt the tag */
2947 if ((p_t2t->ndef_msg_len > 0) &&
2948 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
2949 (p_ret->b_otp)) {
2950 RW_TRACE_WARNING0(
2951 "RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
2952 return (NFC_STATUS_FAILED);
2953 }
2954 p_t2t->p_new_ndef_buffer = p_msg;
2955 p_t2t->new_ndef_msg_len = msg_len;
2956 p_t2t->work_offset = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002957
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002958 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
2959 /* Read first NDEF Block before updating NDEF */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002960
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002961 block = (uint16_t)(p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002962
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002963 if ((block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) &&
2964 (p_t2t->b_read_data)) {
2965 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
2966 p_t2t->block_read = block;
2967 rw_t2t_handle_ndef_write_rsp(
2968 &p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
2969 } else {
2970 if ((status = rw_t2t_read(block)) == NFC_STATUS_OK)
2971 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002972 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002973 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2974 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002975
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002976 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002977}
2978
2979/*******************************************************************************
2980**
2981** Function RW_T2tSetTagReadOnly
2982**
2983** Description This function can be called to set T2 tag as read only.
2984**
2985** Parameters: b_hard_lock: To indicate hard lock the tag or not
2986**
2987** Returns NCI_STATUS_OK, if setting tag as read only was started.
2988** Otherwise, error status.
2989**
2990*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002991tNFC_STATUS RW_T2tSetTagReadOnly(bool b_hard_lock) {
2992 tNFC_STATUS status = NFC_STATUS_FAILED;
2993 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002994
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002995 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2996 RW_TRACE_ERROR1(
2997 "RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - "
2998 "State: %u",
2999 p_t2t->state);
3000 return (NFC_STATUS_FAILED);
3001 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003002
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003003 p_t2t->b_hard_lock = b_hard_lock;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003004
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003005 if (!p_t2t->b_read_hdr) {
3006 /* Read CC block before configuring tag as Read only */
3007 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
3008 if ((status = rw_t2t_read((uint16_t)0)) == NFC_STATUS_OK) {
3009 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
3010 } else
3011 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3012 } else {
3013 if ((status = rw_t2t_soft_lock_tag()) != NFC_STATUS_OK)
3014 p_t2t->b_read_hdr = false;
3015 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003016
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003017 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003018}
3019
Ruchi Kandoi303fec12016-12-14 13:22:38 -08003020#endif /* (RW_NDEF_INCLUDED == TRUE) */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003021
3022#endif /* (NFC_INCLUDED == TRUE) */