blob: 1fb64f8dcef90eebf25b850b20a810c312e5c637 [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
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080028#include "gki.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080029#include "nci_hmsgs.h"
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080030#include "nfc_api.h"
31#include "nfc_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080032#include "rw_api.h"
33#include "rw_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080034
Ruchi Kandoi303fec12016-12-14 13:22:38 -080035#if (RW_NDEF_INCLUDED == TRUE)
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080036
37/* Local static functions */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080038static void rw_t2t_handle_cc_read_rsp(void);
39static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data);
40static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data);
41static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data);
42static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data);
43static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data);
44static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data);
45static uint8_t rw_t2t_get_tag_size(uint8_t* p_data);
46static void rw_t2t_extract_default_locks_info(void);
47static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
48 bool b_update_len);
49static uint8_t rw_t2t_get_ndef_flags(void);
50static uint16_t rw_t2t_get_ndef_max_size(void);
51static tNFC_STATUS rw_t2t_read_locks(void);
52static tNFC_STATUS rw_t2t_read_ndef_last_block(void);
53static void rw_t2t_update_attributes(void);
54static void rw_t2t_update_lock_attributes(void);
55static bool rw_t2t_is_lock_res_byte(uint16_t index);
56static bool rw_t2t_is_read_only_byte(uint16_t index);
57static tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len,
58 bool b_update_len);
59static tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block,
60 uint16_t msg_len,
61 bool b_update_len);
62static tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block);
63static tNFC_STATUS rw_t2t_add_terminator_tlv(void);
64static bool rw_t2t_is_read_before_write_block(uint16_t block,
65 uint16_t* p_block_to_read);
66static tNFC_STATUS rw_t2t_set_cc(uint8_t tms);
67static tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
68 uint16_t locked_area_size);
69static tNFC_STATUS rw_t2t_format_tag(void);
70static tNFC_STATUS rw_t2t_soft_lock_tag(void);
71static tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data);
72static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080073
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080074const uint8_t rw_t2t_mask_bits[8] = {0x01, 0x02, 0x04, 0x08,
75 0x10, 0x20, 0x40, 0x80};
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080076
77/*******************************************************************************
78**
79** Function rw_t2t_handle_rsp
80**
81** Description This function handles response to command sent during
82** NDEF and other tlv operation
83**
84** Returns None
85**
86*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080087void rw_t2t_handle_rsp(uint8_t* p_data) {
88 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080089
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080090 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
91 p_t2t->b_read_hdr = true;
92 memcpy(p_t2t->tag_hdr, p_data, T2T_READ_DATA_LEN);
93 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080094
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080095 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080096 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080097 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
98 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
99 rw_t2t_handle_cc_read_rsp();
100 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
101 rw_t2t_handle_lock_read_rsp(p_data);
102 } else {
103 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800104 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800105 } else if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
106 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
107 if (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] == T2T_CC0_NMN) {
108 rw_t2t_handle_cc_read_rsp();
109 } else {
110 RW_TRACE_WARNING3(
111 "NDEF Detection failed!, CC[0]: 0x%02x, CC[1]: 0x%02x, CC[3]: "
112 "0x%02x",
113 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE],
114 p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
115 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
116 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
117 }
118 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
119 rw_t2t_handle_lock_read_rsp(p_data);
120 } else {
121 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800122 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800123 } else {
124 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
125 rw_t2t_handle_cc_read_rsp();
126 } else {
127 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800128 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800129 }
130 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800131
132 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800133 rw_t2t_handle_config_tag_readonly(p_data);
134 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800135
136 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800137 rw_t2t_handle_format_tag_rsp(p_data);
138 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800139
140 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800141 rw_t2t_handle_ndef_read_rsp(p_data);
142 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800143
144 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800145 rw_t2t_handle_ndef_write_rsp(p_data);
146 break;
147 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800148}
149
150/*******************************************************************************
151**
152** Function rw_t2t_info_to_event
153**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800154** Description This function returns RW event code based on the current
155** state
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800156**
157** Returns RW event code
158**
159*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800160tRW_EVENT rw_t2t_info_to_event(const tT2T_CMD_RSP_INFO* p_info) {
161 tRW_EVENT rw_event;
162 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800163
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800164 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800165 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800166 if (p_t2t->tlv_detect == TAG_NDEF_TLV)
167 rw_event = RW_T2T_NDEF_DETECT_EVT;
168 else
169 rw_event = RW_T2T_TLV_DETECT_EVT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800170
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800171 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800172
173 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800174 rw_event = RW_T2T_NDEF_READ_EVT;
175 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800176
177 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800178 rw_event = RW_T2T_NDEF_WRITE_EVT;
179 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800180
181 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800182 rw_event = RW_T2T_SET_TAG_RO_EVT;
183 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800184
185 case RW_T2T_STATE_CHECK_PRESENCE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800186 rw_event = RW_T2T_PRESENCE_CHECK_EVT;
187 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800188
189 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800190 rw_event = RW_T2T_FORMAT_CPLT_EVT;
191 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800192
193 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800194 rw_event = t2t_info_to_evt(p_info);
195 break;
196 }
197 return rw_event;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800198}
199
200/*******************************************************************************
201**
202** Function rw_t2t_handle_cc_read_rsp
203**
204** Description Handle read cc bytes
205**
206** Returns none
207**
208*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800209static void rw_t2t_handle_cc_read_rsp(void) {
210 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800211
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800212 if (((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) &&
213 (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RO)) ||
214 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
215 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
216 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
217 /* Invalid Version number or RWA byte */
218 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
219 return;
220 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800221
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800222 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800223
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800224 if (rw_t2t_read((uint16_t)T2T_FIRST_DATA_BLOCK) != NFC_STATUS_OK) {
225 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
226 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800227}
228
229/*******************************************************************************
230**
231** Function rw_t2t_ntf_tlv_detect_complete
232**
233** Description Notify TLV detection complete to upper layer
234**
235** Returns none
236**
237*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800238static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status) {
239 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800240 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800241
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800242 if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
243 /* Notify upper layer the result of NDEF detect op */
Myles Watson1361d522017-09-26 13:39:54 -0700244 tRW_DETECT_NDEF_DATA ndef_data = {
245 0,
246 };
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800247 ndef_data.status = status;
248 ndef_data.protocol = NFC_PROTOCOL_T2T;
249 ndef_data.flags = rw_t2t_get_ndef_flags();
250 ndef_data.cur_size = p_t2t->ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800251
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800252 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_FORMATED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800253
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800254 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] == T2T_CC3_RWA_RW)
255 ndef_data.max_size = (uint32_t)rw_t2t_get_ndef_max_size();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800256 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800257 ndef_data.max_size = ndef_data.cur_size;
258
259 if (ndef_data.max_size < ndef_data.cur_size) {
260 ndef_data.flags |= RW_NDEF_FL_READ_ONLY;
261 ndef_data.max_size = ndef_data.cur_size;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800262 }
263
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800264 if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY)) {
265 ndef_data.flags |= RW_NDEF_FL_SOFT_LOCKABLE;
266 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_HARD_LOCKABLE;
267 }
268
269 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700270 tRW_DATA rw_data;
271 rw_data.ndef = ndef_data;
272 (*rw_cb.p_cback)(RW_T2T_NDEF_DETECT_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800273 } else if (p_t2t->tlv_detect == TAG_PROPRIETARY_TLV) {
Myles Watson1361d522017-09-26 13:39:54 -0700274 tRW_T2T_DETECT evt_data;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800275 evt_data.msg_len = p_t2t->prop_msg_len;
276 evt_data.status = status;
277 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700278 /* FIXME: Unsafe cast */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800279 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, (tRW_DATA*)&evt_data);
280 } else {
281 /* Notify upper layer the result of Lock/Mem TLV detect op */
Myles Watson1361d522017-09-26 13:39:54 -0700282 tRW_DETECT_TLV_DATA tlv_data;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800283 tlv_data.protocol = NFC_PROTOCOL_T2T;
284 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
285 tlv_data.num_bytes = p_t2t->num_lockbytes;
286 } else {
287 tlv_data.num_bytes = 0;
288 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++) {
289 tlv_data.num_bytes += p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes;
290 }
291 }
292 tlv_data.status = status;
293 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700294 tRW_DATA rw_data;
295 rw_data.tlv = tlv_data;
296 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800297 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800298}
299
300/*******************************************************************************
301**
302** Function rw_t2t_handle_lock_read_rsp
303**
304** Description Handle response to reading lock bytes
305**
306** Returns none
307**
308*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800309static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data) {
310 uint8_t updated_lock_byte;
311 uint8_t num_locks;
312 uint8_t offset = 0;
313 uint16_t lock_offset;
314 uint16_t base_lock_offset = 0;
315 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
316 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800317
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800318 /* Prepare NDEF/TLV attributes (based on current op) for sending response to
319 * upper layer */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800320
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800321 num_locks = 0;
322 updated_lock_byte = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800323
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800324 /* Extract all lock bytes present in the read 16 bytes
325 * but atleast one lock byte (base lock) should be present in the read 16
326 * bytes */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800327
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800328 while (num_locks < p_t2t->num_lockbytes) {
329 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
330 lock_offset =
331 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
332 p_t2t->lockbyte[num_locks].byte_index;
333 if (updated_lock_byte == 0) {
334 /* The offset of the first lock byte present in the 16 bytes read using
335 * READ command */
336 base_lock_offset = lock_offset;
337 /* Block number used to read may not be the block where lock offset is
338 * present */
339 offset = (uint8_t)(lock_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
340 /* Update the lock byte value in the control block */
341 p_t2t->lockbyte[num_locks].lock_byte = p_data[offset];
342 p_t2t->lockbyte[num_locks].b_lock_read = true;
343 updated_lock_byte++;
344 } else if (lock_offset > base_lock_offset) {
345 /* Atleast one lock byte will get updated in the control block */
346 if ((lock_offset - base_lock_offset + offset) < T2T_READ_DATA_LEN) {
347 /* And this lock byte is also present in the read data */
348 p_t2t->lockbyte[num_locks].lock_byte =
349 p_data[lock_offset - base_lock_offset + offset];
350 p_t2t->lockbyte[num_locks].b_lock_read = true;
351 updated_lock_byte++;
352 } else {
353 /* This lock byte is not present in the read data */
354 block = (uint16_t)(lock_offset / T2T_BLOCK_LEN);
355 block -= block % T2T_READ_BLOCKS;
356 /* send READ command to read this lock byte */
357 if (NFC_STATUS_OK != rw_t2t_read((uint16_t)block)) {
358 /* Unable to send Read command, notify failure status to upper layer
359 */
360 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
361 }
362 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800363 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800364 } else {
365 /* This Lock byte is not present in the read 16 bytes
366 * send READ command to read the lock byte */
367 if (NFC_STATUS_OK !=
368 rw_t2t_read((uint16_t)(lock_offset / T2T_BLOCK_LEN))) {
369 /* Unable to send Read command, notify failure status to upper layer
370 */
371 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
372 }
373 break;
374 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800375 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800376 num_locks++;
377 }
378 if (num_locks == p_t2t->num_lockbytes) {
379 /* All locks are read, notify upper layer */
380 rw_t2t_update_lock_attributes();
381 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_OK);
382 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800383}
384
385/*******************************************************************************
386**
387** Function rw_t2t_handle_tlv_detect_rsp
388**
389** Description Handle TLV detection.
390**
391** Returns none
392**
393*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800394static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data) {
395 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
396 uint16_t offset;
397 uint16_t len = 0;
398 bool failed = false;
399 bool found = false;
400 tRW_EVENT event;
401 uint8_t index;
402 uint8_t count = 0;
403 uint8_t xx;
404 tNFC_STATUS status;
405 tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
406 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
407 uint8_t tlvtype = p_t2t->tlv_detect;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800408
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800409 if (p_t2t->work_offset == 0) {
410 /* Skip UID,Static Lock block,CC*/
411 p_t2t->work_offset = T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN;
412 p_t2t->b_read_data = true;
413 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
414 }
415
416 p_t2t->segment = 0;
417
418 for (offset = 0; offset < T2T_READ_DATA_LEN && !failed && !found;) {
419 if (rw_t2t_is_lock_res_byte((uint16_t)(p_t2t->work_offset + offset)) ==
420 true) {
421 /* Skip locks, reserved bytes while searching for TLV */
422 offset++;
423 continue;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800424 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800425 switch (p_t2t->substate) {
426 case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
427 /* Search for the tlv */
428 p_t2t->found_tlv = p_data[offset++];
429 switch (p_t2t->found_tlv) {
430 case TAG_NULL_TLV: /* May be used for padding. SHALL ignore this */
431 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800432
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800433 case TAG_NDEF_TLV:
434 if (tlvtype == TAG_NDEF_TLV) {
435 /* NDEF Detected, now collect NDEF Attributes including NDEF
436 * Length */
437 index = (offset % T2T_BLOCK_SIZE);
438 /* Backup ndef first block */
439 memcpy(p_t2t->ndef_first_block, &p_data[offset - index], index);
440 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
441 } else if (tlvtype == TAG_PROPRIETARY_TLV) {
442 /* Proprietary TLV can exist after NDEF Tlv so we continue
443 * searching */
444 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
445 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
446 (p_t2t->num_lockbytes > 0)) ||
447 ((tlvtype == TAG_MEM_CTRL_TLV) &&
448 (p_t2t->num_mem_tlvs > 0))) {
449 /* Lock / Memory control tlv cannot exist after NDEF TLV
450 * So when NDEF is found, we stop searching for Lock and Memory
451 * control tlv */
452 found = true;
453 } else {
454 /* While searching for Lock / Memory control tlv, if NDEF TLV is
455 * found
456 * first then our search for Lock /Memory control tlv failed and
457 * we stop here */
458 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800459 }
460 break;
461
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800462 case TAG_LOCK_CTRL_TLV:
463 case TAG_MEM_CTRL_TLV:
464 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
465 break;
466
467 case TAG_PROPRIETARY_TLV:
468 if (tlvtype == TAG_PROPRIETARY_TLV) {
469 index = (offset % T2T_BLOCK_SIZE);
470 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
471 } else {
472 /* NDEF/LOCK/MEM TLV can exist after Proprietary Tlv so we
473 * continue searching, skiping proprietary tlv */
474 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
475 }
476 break;
477
478 case TAG_TERMINATOR_TLV: /* Last TLV block in the data area. Must be
479 no NDEF nessage */
480 if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
481 (p_t2t->num_lockbytes > 0)) ||
482 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
483 /* No more Lock/Memory TLV control tlv in the tag, so stop
484 * searching */
485 found = true;
486 } else {
487 /* NDEF/Lock/Memory/Proprietary TLV cannot exist after Terminator
488 * Tlv */
489 failed = true;
490 }
491 break;
492 default:
493 failed = true;
494 }
495 break;
496
497 case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
498 len = p_data[offset];
499 switch (p_t2t->found_tlv) {
500 case TAG_NDEF_TLV:
501 p_t2t->ndef_header_offset = offset + p_t2t->work_offset;
502 if (len == TAG_LONG_NDEF_LEN_FIELD_BYTE0) {
503 /* The next two bytes constitute length bytes */
504 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
505 } else {
506 /* one byte length field */
507 p_t2t->ndef_msg_len = len;
508 p_t2t->bytes_count = p_t2t->ndef_msg_len;
509 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
510 }
511 break;
512
513 case TAG_PROPRIETARY_TLV:
514 if (len == T2T_LONG_NDEF_LEN_FIELD_BYTE0) {
515 /* The next two bytes constitute length bytes */
516 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
517 } else {
518 /* one byte length field */
519 p_t2t->prop_msg_len = len;
520 p_t2t->bytes_count = p_t2t->prop_msg_len;
521 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
522 }
523 break;
524 }
525 offset++;
526 break;
527
528 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
529 switch (p_t2t->found_tlv) {
530 case TAG_LOCK_CTRL_TLV:
531 case TAG_MEM_CTRL_TLV:
532
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800533 len = p_data[offset];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800534 if (len == TAG_DEFAULT_TLV_LEN) {
535 /* Valid Lock control TLV */
536 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
537 p_t2t->bytes_count = TAG_DEFAULT_TLV_LEN;
538 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
539 (p_t2t->num_lockbytes > 0)) ||
540 ((tlvtype == TAG_MEM_CTRL_TLV) &&
541 (p_t2t->num_mem_tlvs > 0))) {
542 /* Stop searching for Lock/ Memory control tlv */
543 found = true;
544 } else {
545 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800546 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800547 break;
548
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800549 case TAG_NDEF_TLV:
550 case TAG_PROPRIETARY_TLV:
551 /* The first length byte */
552 p_t2t->bytes_count = (uint8_t)p_data[offset];
553 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800554 break;
555 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800556 offset++;
557 break;
558
559 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
560 /* Prepare NDEF Message length */
561 p_t2t->bytes_count = (p_t2t->bytes_count << 8) + p_data[offset];
562 if (p_t2t->found_tlv == TAG_NDEF_TLV) {
563 p_t2t->ndef_msg_len = p_t2t->bytes_count;
564 } else if (p_t2t->found_tlv == TAG_PROPRIETARY_TLV) {
565 p_t2t->prop_msg_len = p_t2t->bytes_count;
566 }
567 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
568 offset++;
569 break;
570
571 case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
572 switch (p_t2t->found_tlv) {
573 case TAG_NDEF_TLV:
574 if ((p_t2t->bytes_count == p_t2t->ndef_msg_len) &&
575 (tlvtype == TAG_NDEF_TLV)) {
576 /* The first byte offset after length field */
577 p_t2t->ndef_msg_offset = offset + p_t2t->work_offset;
578 }
579 /* Reduce number of NDEF bytes remaining to pass over NDEF TLV */
580 if (p_t2t->bytes_count > 0) p_t2t->bytes_count--;
581
582 if (tlvtype == TAG_NDEF_TLV) {
583 found = true;
584 p_t2t->ndef_status = T2T_NDEF_DETECTED;
585 } else if (p_t2t->bytes_count == 0) {
586 /* Next byte could be a different TLV */
587 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
588 }
589 break;
590
591 case TAG_LOCK_CTRL_TLV:
592 p_t2t->bytes_count--;
593 if ((tlvtype == TAG_LOCK_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
594 /* Collect Lock TLV */
595 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
596 if (p_t2t->bytes_count == 0) {
597 /* Lock TLV is collected and buffered in tlv_value, now decode
598 * it */
599 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
600 (p_t2t->tlv_value[0] >> 4) & 0x0F;
601 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset *=
602 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
603 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset +=
604 p_t2t->tlv_value[0] & 0x0F;
605 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
606 (uint8_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
607 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits =
608 p_t2t->tlv_value[1];
609 count = p_t2t->tlv_value[1] / 8 +
610 ((p_t2t->tlv_value[1] % 8 != 0) ? 1 : 0);
611
612 /* Extract lockbytes info addressed by this Lock TLV */
613 xx = 0;
614 while (xx < count) {
615 p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index =
616 p_t2t->num_lock_tlvs;
617 p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index = xx;
618 p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read = false;
619 xx++;
620 p_t2t->num_lockbytes++;
621 }
622 p_t2t->num_lock_tlvs++;
623 rw_t2t_update_attributes();
624 /* Next byte could be a different TLV */
625 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
626 }
627 } else {
628 /* If not looking for lock/ndef tlv, just skip this Lock TLV */
629 if (p_t2t->bytes_count == 0) {
630 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
631 }
632 }
633 break;
634
635 case TAG_MEM_CTRL_TLV:
636 p_t2t->bytes_count--;
637 if ((tlvtype == TAG_MEM_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
638 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
639 if (p_t2t->bytes_count == 0) {
640 if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS) {
641 RW_TRACE_ERROR0(
642 "rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated "
643 "for Memory tlv has reached");
644 failed = true;
645 } else {
646 /* Extract memory control tlv */
647 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
648 (p_t2t->tlv_value[0] >> 4) & 0x0F;
649 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
650 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
651 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
652 p_t2t->tlv_value[0] & 0x0F;
653 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
654 p_t2t->tlv_value[1];
655 p_t2t->num_mem_tlvs++;
656 rw_t2t_update_attributes();
657 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
658 }
659 }
660 } else {
661 if (p_t2t->bytes_count == 0) {
662 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
663 }
664 }
665 break;
666
667 case TAG_PROPRIETARY_TLV:
668 p_t2t->bytes_count--;
669 if (tlvtype == TAG_PROPRIETARY_TLV) {
670 found = true;
671 p_t2t->prop_msg_len = len;
672 } else {
673 if (p_t2t->bytes_count == 0) {
674 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
675 }
676 }
677 break;
678 }
679 offset++;
680 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800681 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800682 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800683
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800684 p_t2t->work_offset += T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800685
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800686 event = rw_t2t_info_to_event(p_cmd_rsp_info);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800687
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800688 /* If not found and not failed, read next block and search tlv */
689 if (!found && !failed) {
690 if (p_t2t->work_offset >=
691 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR)) {
692 if (((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0)) ||
693 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
694 found = true;
695 } else {
696 failed = true;
697 }
698 } else {
699 if (rw_t2t_read((uint16_t)((p_t2t->work_offset / T2T_BLOCK_LEN) +
700 T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
701 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800702 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800703 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800704
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800705 if (failed || found) {
706 if (tlvtype == TAG_LOCK_CTRL_TLV) {
707 /* Incase no Lock control tlv is present then look for default dynamic
708 * lock bytes */
709 rw_t2t_extract_default_locks_info();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800710
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800711 /* Send command to read the dynamic lock bytes */
712 status = rw_t2t_read_locks();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800713
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800714 if (status != NFC_STATUS_CONTINUE) {
715 /* If unable to read a lock/all locks read, notify upper layer */
716 rw_t2t_update_lock_attributes();
717 rw_t2t_ntf_tlv_detect_complete(status);
718 }
719 } else if (tlvtype == TAG_NDEF_TLV) {
720 rw_t2t_extract_default_locks_info();
721
722 if (failed) {
723 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
724 } else {
725 /* NDEF present,Send command to read the dynamic lock bytes */
726 status = rw_t2t_read_locks();
727 if (status != NFC_STATUS_CONTINUE) {
728 /* If unable to read a lock/all locks read, notify upper layer */
729 rw_t2t_update_lock_attributes();
730 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800731 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800732 }
733 } else {
734 /* Notify Memory/ Proprietary tlv detect result */
735 status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
736 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800737 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800738 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800739}
740
741/*******************************************************************************
742**
743** Function rw_t2t_read_locks
744**
745** Description This function will send command to read next unread locks
746**
747** Returns NFC_STATUS_OK, if all locks are read successfully
748** NFC_STATUS_FAILED, if reading locks failed
749** NFC_STATUS_CONTINUE, if reading locks is in progress
750**
751*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800752tNFC_STATUS rw_t2t_read_locks(void) {
753 uint8_t num_locks = 0;
754 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
755 tNFC_STATUS status = NFC_STATUS_CONTINUE;
756 uint16_t offset;
757 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800758
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800759 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) ||
760 (p_t2t->skip_dyn_locks)) {
761 /* Skip reading dynamic lock bytes if CC is set as Read only or layer above
762 * instructs to skip */
763 while (num_locks < p_t2t->num_lockbytes) {
764 p_t2t->lockbyte[num_locks].lock_byte = 0x00;
765 p_t2t->lockbyte[num_locks].b_lock_read = true;
766 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800767 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800768 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800769
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800770 while (num_locks < p_t2t->num_lockbytes) {
771 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
772 /* Send Read command to read the first un read locks */
773 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
774 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800775
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800776 /* Read 16 bytes where this lock byte is present */
777 block = (uint16_t)(offset / T2T_BLOCK_LEN);
778 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800779
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800780 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
781 /* send READ8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800782 status = rw_t2t_read((uint16_t)block);
783 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800784 /* Reading Locks */
785 status = NFC_STATUS_CONTINUE;
786 } else {
787 status = NFC_STATUS_FAILED;
788 }
789 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800790 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800791 num_locks++;
792 }
793 if (num_locks == p_t2t->num_lockbytes) {
794 /* All locks are read */
795 status = NFC_STATUS_OK;
796 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800797
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800798 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800799}
800
801/*******************************************************************************
802**
803** Function rw_t2t_extract_default_locks_info
804**
805** Description This function will prepare lockbytes information for default
806** locks present in the tag in the absence of lock control tlv.
807** Adding a virtual lock control tlv for these lock bytes for
808** easier manipulation.
809**
810** Returns None
811**
812*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800813void rw_t2t_extract_default_locks_info(void) {
814 uint8_t num_dynamic_lock_bits;
815 uint8_t num_dynamic_lock_bytes;
816 uint8_t xx;
817 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
818 const tT2T_INIT_TAG* p_ret;
819 uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800820
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800821 if ((p_t2t->num_lock_tlvs == 0) &&
822 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
823 /* No Lock control tlv is detected. Indicates lock bytes are present in
824 * default location */
825 /* Add a virtual Lock tlv to map this default lock location */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800826 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
827 if (p_ret != NULL) bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800828
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800829 num_dynamic_lock_bits =
830 ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
831 (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
832 bytes_locked_per_lock_bit;
833 num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
834 num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800835
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800836 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
837 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
838 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
839 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
840 bytes_locked_per_lock_bit;
841 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 -0800842
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800843 /* Based on tag data size the number of locks present in the default
844 * location changes */
845 for (xx = 0; xx < num_dynamic_lock_bytes; xx++) {
846 p_t2t->lockbyte[xx].tlv_index = p_t2t->num_lock_tlvs;
847 p_t2t->lockbyte[xx].byte_index = xx;
848 p_t2t->lockbyte[xx].b_lock_read = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800849 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800850 p_t2t->num_lockbytes = num_dynamic_lock_bytes;
851 p_t2t->num_lock_tlvs = 1;
852 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800853}
854
855/*******************************************************************************
856**
857** Function rw_t2t_read_ndef_last_block
858**
859** Description This function will locate and read the last ndef block.
860** The last ndef block refers to the tag block where last byte
861** of new ndef message will reside. Also this function will
862** locate the offset of Terminator TLV based on the size of
863** new NDEF Message
864**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800865** Returns NCI_STATUS_OK, if able to locate last ndef block & read
866** started. Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800867**
868*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800869tNFC_STATUS rw_t2t_read_ndef_last_block(void) {
870 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
871 uint16_t header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN)
872 ? T2T_LONG_NDEF_LEN_FIELD_LEN
873 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
874 uint16_t num_ndef_bytes;
875 uint16_t total_ndef_bytes;
876 uint16_t last_ndef_byte_offset;
877 uint16_t terminator_tlv_byte_index;
878 tNFC_STATUS status;
879 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800880
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800881 total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
882 num_ndef_bytes = 0;
883 last_ndef_byte_offset = p_t2t->ndef_header_offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800884
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800885 /* Locate NDEF final block based on the size of new NDEF Message */
886 while (num_ndef_bytes < total_ndef_bytes) {
887 if (rw_t2t_is_lock_res_byte((uint16_t)(last_ndef_byte_offset)) == false)
888 num_ndef_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800889
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800890 last_ndef_byte_offset++;
891 }
892 p_t2t->ndef_last_block_num =
893 (uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
894 block = p_t2t->ndef_last_block_num;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800895
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800896 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
897 /* Read NDEF last block before updating */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800898 status = rw_t2t_read(block);
899 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800900 if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
901 /* Locate Terminator TLV Block */
902 total_ndef_bytes++;
903 terminator_tlv_byte_index = last_ndef_byte_offset;
904
905 while (num_ndef_bytes < total_ndef_bytes) {
906 if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
907 false)
908 num_ndef_bytes++;
909
910 terminator_tlv_byte_index++;
911 }
912
913 p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
914 } else {
915 /* No space for Terminator TLV */
916 p_t2t->terminator_byte_index = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800917 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800918 }
919 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800920}
921
922/*******************************************************************************
923**
924** Function rw_t2t_read_terminator_tlv_block
925**
926** Description This function will read the block where terminator tlv will
927** be added later
928**
929** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
930**
931*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800932tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
933 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
934 tNFC_STATUS status;
935 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800936
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800937 /* Send read command to read base block (Block % 4==0) where this block is
938 * also read as part of 16 bytes */
939 block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
940 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800941
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800942 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
943 /* Read the block where Terminator TLV may be added later during NDEF Write
944 * operation */
945 status = rw_t2t_read(block);
946 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800947}
948
949/*******************************************************************************
950**
951** Function rw_t2t_read_ndef_next_block
952**
953** Description This function will read the tag block passed as argument
954**
955** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
956**
957*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800958tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block) {
959 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
960 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800961
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800962 /* Send read command to read base block (Block % 4==0) where this block is
963 * also read as part of 16 bytes */
964 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800965
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800966 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
967 /* Read the block */
968 status = rw_t2t_read(block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800969
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800970 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800971}
972
973/*******************************************************************************
974**
975** Function rw_t2t_is_read_before_write_block
976**
977** Description This function will check if the block has to be read before
978** writting to avoid over writting in to lock/reserved bytes
979** present in the block.
980** If no bytes in the block can be overwritten it moves in to
981** next block and check. Finally it finds a block where part of
982** ndef bytes can exist and check if the whole block can be
983** updated or only part of block can be modified.
984**
985** Returns TRUE, if the block returned should be read before writting
986** FALSE, if the block need not be read as it was already
987** read or during NDEF write we may completely overwrite
988** the block and there is no reserved or locked bytes in
989** that block
990**
991*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800992static bool rw_t2t_is_read_before_write_block(uint16_t block,
993 uint16_t* p_block_to_read) {
994 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
995 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
996 uint8_t count;
997 uint8_t index;
998 uint16_t tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
999 bool read_before_write = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001000
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001001 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1002 /* First NDEF block is already read */
1003 read_before_write = false;
1004 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
1005 } else if (block == p_t2t->ndef_last_block_num) {
1006 /* Last NDEF block is already read */
1007 read_before_write = false;
1008 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1009 } else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) {
1010 /* Terminator tlv block is already read */
1011 read_before_write = false;
1012 memcpy(p_t2t->ndef_read_block, p_t2t->terminator_tlv_block, T2T_BLOCK_SIZE);
1013 } else {
1014 count = 0;
1015 while (block < tag_size) {
1016 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001017
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001018 while (index < T2T_BLOCK_SIZE) {
1019 /* check if it is a reserved or locked byte */
1020 if (rw_t2t_is_lock_res_byte(
1021 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1022 count++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001023 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001024 index++;
1025 }
1026 if (count == T2T_BLOCK_SIZE) {
1027 /* All the bytes in the block are free to NDEF write */
1028 read_before_write = false;
1029 break;
1030 } else if (count == 0) {
1031 /* The complete block is not free for NDEF write */
1032 index = 0;
1033 block++;
1034 } else {
1035 /* The block has reseved byte (s) or locked byte (s) or both */
1036 read_before_write = true;
1037 break;
1038 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001039 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001040 }
1041 /* Return the block to read next before NDEF write */
1042 *p_block_to_read = block;
1043 return read_before_write;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001044}
1045
1046/*******************************************************************************
1047**
1048** Function rw_t2t_write_ndef_first_block
1049**
1050** Description This function will write the first NDEF block with Length
1051** field reset to zero.
1052** Also after writting NDEF this function may be called to
1053** update new NDEF length
1054**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001055** Returns NCI_STATUS_OK, if write was started.
1056** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001057**
1058*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001059tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len, bool b_update_len) {
1060 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1061 uint8_t new_lengthfield_len;
1062 uint8_t write_block[4];
1063 uint8_t block;
1064 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1065 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1066 tNFC_STATUS status;
1067 uint8_t length_field[3];
1068 uint8_t index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001069
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001070 p_t2t->work_offset = 0;
1071 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1072 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1073 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1074 if (new_lengthfield_len == 3) {
1075 /* New NDEF is Long NDEF */
1076 if (msg_len == 0) {
1077 /* Clear NDEF length field */
1078 length_field[0] = 0x00;
1079 length_field[1] = 0x00;
1080 length_field[2] = 0x00;
1081 } else {
1082 /* Update NDEF length field with new NDEF Msg len */
1083 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1084 length_field[1] = (uint8_t)(msg_len >> 8);
1085 length_field[2] = (uint8_t)(msg_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001086 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001087 } else {
1088 /* New NDEF is Short NDEF */
1089 length_field[0] = (uint8_t)(msg_len);
1090 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001091
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001092 /* updating ndef_first_block with new ndef message */
1093 memcpy(write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001094
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001095 index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1096 block = (uint8_t)(p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001097
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001098 while (p_t2t->work_offset == 0 && block < total_blocks) {
1099 /* update length field */
1100 while (index < T2T_BLOCK_SIZE &&
1101 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1102 if (rw_t2t_is_lock_res_byte(
1103 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1104 write_block[index] = length_field[p_t2t->work_offset];
1105 p_t2t->work_offset++;
1106 }
1107 index++;
1108 if (p_t2t->work_offset == new_lengthfield_len) {
1109 break;
1110 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001111 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001112 /* If more space in this block then add ndef message */
1113 while (index < T2T_BLOCK_SIZE &&
1114 p_t2t->work_offset <
1115 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1116 if (rw_t2t_is_lock_res_byte(
1117 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1118 write_block[index] =
1119 p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1120 p_t2t->work_offset++;
1121 }
1122 index++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001123 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001124 if (p_t2t->work_offset == 0) {
1125 /* If no bytes are written move to next block */
1126 index = 0;
1127 block++;
1128 if (block == p_t2t->ndef_last_block_num) {
1129 memcpy(write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1130 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001131 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001132 }
1133 if (p_t2t->work_offset == 0) {
1134 status = NFC_STATUS_FAILED;
1135 } else {
1136 rw_t2t_update_cb(block, write_block, b_update_len);
1137 /* Update the identified block with newly prepared data */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001138 status = rw_t2t_write(block, write_block);
1139 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001140 p_t2t->b_read_data = false;
1141 }
1142 }
1143 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001144}
1145
1146/*******************************************************************************
1147**
1148** Function rw_t2t_write_ndef_next_block
1149**
1150** Description This function can be called to write an NDEF message block
1151**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001152** Returns NCI_STATUS_OK, if write was started.
1153** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001154**
1155*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001156tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block, uint16_t msg_len,
1157 bool b_update_len) {
1158 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1159 uint8_t new_lengthfield_len;
1160 uint8_t write_block[4];
1161 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1162 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1163 uint16_t initial_offset;
1164 uint8_t length_field[3];
1165 uint8_t index;
1166 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001167
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001168 /* Write NDEF Message */
1169 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1170 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1171 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001172
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001173 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001174
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001175 memcpy(write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001176
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001177 if (p_t2t->work_offset >= new_lengthfield_len) {
1178 /* Length field is updated, write ndef message field */
1179 initial_offset = p_t2t->work_offset;
1180 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1181 while (index < T2T_BLOCK_SIZE &&
1182 p_t2t->work_offset <
1183 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1184 if (rw_t2t_is_lock_res_byte(
1185 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1186 write_block[index] =
1187 p_t2t
1188 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1189 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001190 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001191 index++;
1192 }
1193 if (p_t2t->work_offset == initial_offset) {
1194 index = 0;
1195 block++;
1196 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001197 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001198 } else {
1199 /* Complete writting Length field and then write ndef message */
1200 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1201 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1202 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1203 if (new_lengthfield_len == 3) {
1204 /* New NDEF is Long NDEF */
1205 if (msg_len == 0) {
1206 length_field[0] = 0x00;
1207 length_field[1] = 0x00;
1208 length_field[2] = 0x00;
1209 } else {
1210 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1211 length_field[1] = (uint8_t)(msg_len >> 8);
1212 length_field[2] = (uint8_t)(msg_len);
1213 }
1214 } else {
1215 /* New NDEF is short NDEF */
1216 length_field[0] = (uint8_t)(msg_len);
1217 }
1218 initial_offset = p_t2t->work_offset;
1219 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1220 /* Update length field */
1221 while (index < T2T_BLOCK_SIZE &&
1222 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1223 if (rw_t2t_is_lock_res_byte(
1224 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1225 write_block[index] = length_field[p_t2t->work_offset];
1226 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001227 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001228 index++;
1229 if (p_t2t->work_offset == new_lengthfield_len) {
1230 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001231 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001232 }
1233 /* Update ndef message field */
1234 while (index < T2T_BLOCK_SIZE &&
1235 p_t2t->work_offset <
1236 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1237 if (rw_t2t_is_lock_res_byte(
1238 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1239 write_block[index] =
1240 p_t2t
1241 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1242 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001243 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001244 index++;
1245 }
1246 if (p_t2t->work_offset == initial_offset) {
1247 index = 0;
1248 block++;
1249 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001250 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001251 }
1252 if (p_t2t->work_offset == initial_offset) {
1253 status = NFC_STATUS_FAILED;
1254 } else {
1255 rw_t2t_update_cb(block, write_block, b_update_len);
1256 /* Write the NDEF Block */
1257 status = rw_t2t_write(block, write_block);
1258 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001259
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001260 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001261}
1262
1263/*******************************************************************************
1264**
1265** Function rw_t2t_update_cb
1266**
1267** Description This function can be called to write an NDEF message block
1268**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001269** Returns NCI_STATUS_OK, if write was started.
1270** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001271**
1272*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001273static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
1274 bool b_update_len) {
1275 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1276 uint8_t new_lengthfield_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001277
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001278 /* Write NDEF Message */
1279 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1280 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1281 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001282
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001283 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1284 /* Update ndef first block if the 'block' points to ndef first block */
1285 memcpy(p_t2t->ndef_first_block, p_write_block, T2T_BLOCK_SIZE);
1286 }
1287 if (p_t2t->terminator_byte_index / T2T_BLOCK_SIZE == block) {
1288 /* Update terminator block if the 'block' points to terminator tlv block */
1289 memcpy(p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1290 }
1291 if (b_update_len == false) {
1292 if (block == p_t2t->ndef_last_block_num) {
1293 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1294 p_t2t->work_offset = 0;
1295 /* Update ndef final block if the 'block' points to ndef final block */
1296 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
1297 } else {
1298 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001299 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001300 } else {
1301 if (block == p_t2t->ndef_last_block_num) {
1302 /* Update the backup of Ndef final block TLV block */
1303 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001304 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001305
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001306 if (p_t2t->work_offset >= new_lengthfield_len) {
1307 if (p_t2t->terminator_byte_index != 0) {
1308 /* Add Terminator TLV as part of NDEF Write operation */
1309 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1310 } else {
1311 /* Skip adding Terminator TLV */
1312 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1313 }
1314 } else {
1315 /* Part of NDEF Message Len should be added in the next block */
1316 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001317 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001318 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001319}
1320
1321/*******************************************************************************
1322**
1323** Function rw_t2t_get_ndef_flags
1324**
1325** Description Prepare NDEF Flags
1326**
1327** Returns NDEF Flag value
1328**
1329*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001330static uint8_t rw_t2t_get_ndef_flags(void) {
1331 uint8_t flags = 0;
1332 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1333 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001334
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001335 flags |= RW_NDEF_FL_SUPPORTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001336
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001337 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) ||
1338 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1339 flags |= RW_NDEF_FL_FORMATABLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001340
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001341 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1342 flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001343
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001344 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1345 (p_ret->b_otp)) {
1346 /* Set otp flag */
1347 flags |= RW_NDEF_FL_OTP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001348
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001349 /* Set Read only flag if otp tag already has NDEF Message */
1350 if (p_t2t->ndef_msg_len) flags |= RW_NDEF_FL_READ_ONLY;
1351 }
1352 return flags;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001353}
1354
1355/*******************************************************************************
1356**
1357** Function rw_t2t_get_ndef_max_size
1358**
1359** Description Calculate maximum size of NDEF message that can be written
1360** on to the tag
1361**
1362** Returns Maximum size of NDEF Message
1363**
1364*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001365static uint16_t rw_t2t_get_ndef_max_size(void) {
1366 uint16_t offset;
1367 uint8_t xx;
1368 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1369 uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
1370 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
1371 p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001372
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001373 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1374 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001375
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001376 offset = p_t2t->ndef_msg_offset;
1377 p_t2t->max_ndef_msg_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001378
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001379 if ((tag_size < T2T_STATIC_SIZE) ||
1380 (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
1381 ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
1382 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
1383 /* Tag not formated, assume static tag */
1384 p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
1385 T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001386 return p_t2t->max_ndef_msg_len;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001387 }
1388
1389 /* Starting from NDEF Message offset find the first locked data byte */
1390 while (offset < tag_size) {
1391 if (rw_t2t_is_lock_res_byte((uint16_t)offset) == false) {
1392 if (rw_t2t_is_read_only_byte((uint16_t)offset) == true) break;
1393 p_t2t->max_ndef_msg_len++;
1394 }
1395 offset++;
1396 }
1397 /* NDEF Length field length changes based on NDEF size */
1398 if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
1399 ((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
1400 T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
1401 p_t2t->max_ndef_msg_len -=
1402 (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1403 ? 1
1404 : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1405 }
1406 return p_t2t->max_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001407}
1408
1409/*******************************************************************************
1410**
1411** Function rw_t2t_add_terminator_tlv
1412**
1413** Description This function will add terminator TLV after NDEF Message
1414**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001415** Returns NCI_STATUS_OK, if write was started.
1416** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001417**
1418*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001419tNFC_STATUS rw_t2t_add_terminator_tlv(void) {
1420 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1421 tNFC_STATUS status;
1422 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001423
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001424 /* Add Terminator TLV after NDEF Message */
1425 p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
1426 TAG_TERMINATOR_TLV;
1427 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001428
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001429 block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
1430 status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001431
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001432 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001433}
1434
1435/*******************************************************************************
1436**
1437** Function rw_t2t_handle_ndef_read_rsp
1438**
1439** Description This function handles reading an NDEF message.
1440**
1441** Returns none
1442**
1443*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001444static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data) {
1445 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1446 tRW_READ_DATA evt_data;
1447 uint16_t len;
1448 uint16_t offset;
1449 bool failed = false;
1450 bool done = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001451
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001452 /* On the first read, adjust for any partial block offset */
1453 offset = 0;
1454 len = T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001455
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001456 if (p_t2t->work_offset == 0) {
1457 /* The Ndef Message offset may be present in the read 16 bytes */
1458 offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1459 }
1460
1461 /* Skip all reserved and lock bytes */
1462 while ((offset < len) && (p_t2t->work_offset < p_t2t->ndef_msg_len))
1463
1464 {
1465 if (rw_t2t_is_lock_res_byte(
1466 (uint16_t)(offset + p_t2t->block_read * T2T_BLOCK_LEN)) == false) {
1467 /* Collect the NDEF Message */
1468 p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1469 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001470 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001471 offset++;
1472 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001473
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001474 if (p_t2t->work_offset >= p_t2t->ndef_msg_len) {
1475 done = true;
1476 p_t2t->ndef_status = T2T_NDEF_READ;
1477 } else {
1478 /* Read next 4 blocks */
1479 if (rw_t2t_read((uint16_t)(p_t2t->block_read + T2T_READ_BLOCKS)) !=
1480 NFC_STATUS_OK)
1481 failed = true;
1482 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001483
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001484 if (failed || done) {
1485 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1486 evt_data.p_data = NULL;
1487 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001488 tRW_DATA rw_data;
1489 rw_data.data = evt_data;
1490 (*rw_cb.p_cback)(RW_T2T_NDEF_READ_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001491 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001492}
1493
1494/*******************************************************************************
1495**
1496** Function rw_t2t_handle_ndef_write_rsp
1497**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001498** Description Handle response received to reading (or part of) NDEF
1499** message.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001500**
1501** Returns none
1502**
1503*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001504static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data) {
1505 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1506 tRW_READ_DATA evt_data;
1507 bool failed = false;
1508 bool done = false;
1509 uint16_t block;
1510 uint8_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001511
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001512 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001513 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1514
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001515 /* Backup the read NDEF first block */
1516 memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1517 /* Read ndef final block */
1518 if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
1519 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001520
1521 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1522
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001523 offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
1524 T2T_BLOCK_SIZE;
1525 /* Backup the read NDEF final block */
1526 memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1527 if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
1528 p_t2t->ndef_last_block_num) {
1529 /* If Terminator TLV will reside on the NDEF Final block */
1530 memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
1531 T2T_BLOCK_LEN);
1532 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1533 failed = true;
1534 } else if (p_t2t->terminator_byte_index != 0) {
1535 /* If there is space for Terminator TLV and if it will reside outside
1536 * NDEF Final block */
1537 if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
1538 } else {
1539 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1540 failed = true;
1541 }
1542 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001543
1544 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1545
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001546 offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
1547 p_t2t->block_read) *
1548 T2T_BLOCK_SIZE);
1549 /* Backup the read Terminator TLV block */
1550 memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001551
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001552 /* Write the first block for new NDEF Message */
1553 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1554 failed = true;
1555 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001556
1557 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1558
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001559 offset = (uint8_t)(p_t2t->ndef_read_block_num - p_t2t->block_read) *
1560 T2T_BLOCK_SIZE;
1561 /* Backup read block */
1562 memcpy(p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001563
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001564 /* Update the block with new NDEF Message */
1565 if (rw_t2t_write_ndef_next_block(p_t2t->ndef_read_block_num, 0x0000,
1566 false) != NFC_STATUS_OK)
1567 failed = true;
1568 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001569
1570 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1571 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001572 if (rw_t2t_is_read_before_write_block(
1573 (uint16_t)(p_t2t->block_written + 1), &block) == true) {
1574 p_t2t->ndef_read_block_num = block;
1575 /* If only part of the block is going to be updated read the block to
1576 retain previous data for
1577 unchanged part of the block */
1578 if (rw_t2t_read_ndef_next_block(block) != NFC_STATUS_OK) failed = true;
1579 } else {
1580 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK) {
1581 /* Directly write the block with new NDEF contents as whole block is
1582 * going to be updated */
1583 if (rw_t2t_write_ndef_next_block(block, p_t2t->new_ndef_msg_len,
1584 true) != NFC_STATUS_OK)
1585 failed = true;
1586 } else {
1587 /* Directly write the block with new NDEF contents as whole block is
1588 * going to be updated */
1589 if (rw_t2t_write_ndef_next_block(block, 0x0000, false) !=
1590 NFC_STATUS_OK)
1591 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001592 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001593 }
1594 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001595
1596 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001597 /* Write the next block for new NDEF Message */
1598 p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1599 if (rw_t2t_is_read_before_write_block((uint16_t)(p_t2t->ndef_write_block),
1600 &block) == true) {
1601 /* If only part of the block is going to be updated read the block to
1602 retain previous data for
1603 part of the block thats not going to be changed */
1604 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1605 if (rw_t2t_read(block) != NFC_STATUS_OK) failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001606
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001607 } else {
1608 /* Update NDEF Message Length in the Tag */
1609 if (rw_t2t_write_ndef_first_block(p_t2t->new_ndef_msg_len, true) !=
1610 NFC_STATUS_OK)
1611 failed = true;
1612 }
1613 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001614
1615 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001616 /* Backup read block */
1617 memcpy(p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001618
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001619 /* Update the block with new NDEF Message */
1620 if (rw_t2t_write_ndef_next_block(p_t2t->block_read,
1621 p_t2t->new_ndef_msg_len,
1622 true) == NFC_STATUS_OK)
1623 p_t2t->ndef_write_block = p_t2t->block_read + 1;
1624 else
1625 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001626
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001627 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001628
1629 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001630 if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
1631 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001632
1633 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001634 done = true;
1635 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001636
1637 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001638 break;
1639 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001640
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001641 if (failed || done) {
1642 evt_data.p_data = NULL;
1643 /* NDEF WRITE Operation is done, inform up the stack */
1644 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1645 if (done) {
1646 if ((p_t2t->ndef_msg_len >= 0x00FF) &&
1647 (p_t2t->new_ndef_msg_len < 0x00FF)) {
1648 p_t2t->ndef_msg_offset -= 2;
1649 } else if ((p_t2t->new_ndef_msg_len >= 0x00FF) &&
1650 (p_t2t->ndef_msg_len < 0x00FF)) {
1651 p_t2t->ndef_msg_offset += 2;
1652 }
1653 p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001654 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001655 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001656 tRW_DATA rw_data;
1657 rw_data.data = evt_data;
1658 (*rw_cb.p_cback)(RW_T2T_NDEF_WRITE_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001659 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001660}
1661
1662/*******************************************************************************
1663**
1664** Function rw_t2t_get_tag_size
1665**
1666** Description This function calculates tag data area size from data read
1667** from block with version number
1668**
1669** Returns TMS of the tag
1670**
1671*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001672static uint8_t rw_t2t_get_tag_size(uint8_t* p_data) {
1673 uint16_t LchunkSize = 0;
1674 uint16_t Num_LChuncks = 0;
1675 uint16_t tms = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001676
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001677 LchunkSize = (uint16_t)p_data[2] << 8 | p_data[3];
1678 Num_LChuncks = (uint16_t)p_data[4] << 8 | p_data[5];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001679
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001680 tms = (uint16_t)(LchunkSize * Num_LChuncks);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001681
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001682 tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001683
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001684 tms /= 0x08;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001685
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001686 return (uint8_t)tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001687}
1688
1689/*******************************************************************************
1690**
1691** Function rw_t2t_handle_config_tag_readonly
1692**
1693** Description This function handles configure type 2 tag as read only
1694**
1695** Returns none
1696**
1697*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001698static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data) {
1699 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1700 tNFC_STATUS status = NFC_STATUS_FAILED;
1701 bool b_notify = false;
1702 uint8_t write_block[T2T_BLOCK_SIZE];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001703 bool b_pending = false;
1704 uint8_t read_lock = 0;
1705 uint8_t num_locks = 0;
1706 uint16_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001707
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001708 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001709 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1710
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001711 /* First soft lock the tag */
1712 rw_t2t_soft_lock_tag();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001713
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001714 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001715
1716 case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1717
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001718 /* Successfully soft locked! Update Tag header for future reference */
1719 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1720 if (!p_t2t->b_hard_lock) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001721 /* Tag configuration complete */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001722 status = NFC_STATUS_OK;
Ruchi Kandoi4a179642017-01-04 10:04:48 -08001723 b_notify = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001724 break;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001725 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001726
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001727 /* Coverity: [FALSE-POSITIVE error] intended fall through */
1728 /* Missing break statement between cases in switch statement */
1729 /* fall through */
1730 case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001731
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001732 num_locks = 0;
1733
1734 while (num_locks < p_t2t->num_lockbytes) {
1735 if (p_t2t->lockbyte[num_locks].lock_status ==
1736 RW_T2T_LOCK_UPDATE_INITIATED) {
1737 /* Update control block as one or more dynamic lock byte (s) are set
1738 */
1739 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1740 }
1741 if (!b_pending &&
1742 p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
1743 /* One or more dynamic lock bits are not set */
1744 b_pending = true;
1745 read_lock = num_locks;
1746 }
1747 num_locks++;
1748 }
1749
1750 if (b_pending) {
1751 /* Read the block where dynamic lock bits are present to avoid writing
1752 * to NDEF bytes in the same block */
1753 offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
1754 p_t2t->lockbyte[read_lock].byte_index;
1755 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1756 status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
1757 } else {
1758 /* Now set Static lock bits as no more dynamic lock bits to set */
1759
1760 /* Copy the internal bytes */
1761 memcpy(write_block,
1762 &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
1763 T2T_INTERNAL_BYTES_LEN);
1764 /* Set all Static lock bits */
1765 write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1766 write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1767 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1768 status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1769 }
1770 break;
1771
1772 case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1773 /* Now set the dynamic lock bits present in the block read now */
1774 status = rw_t2t_set_dynamic_lock_bits(p_data);
1775 break;
1776
1777 case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1778 /* Tag configuration complete */
1779 status = NFC_STATUS_OK;
1780 b_notify = true;
1781 break;
1782 }
1783
1784 if (status != NFC_STATUS_OK || b_notify) {
1785 /* Notify upper layer the result of Configuring Tag as Read only */
Myles Watson1361d522017-09-26 13:39:54 -07001786 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001787 evt.status = status;
1788 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001789 (*rw_cb.p_cback)(RW_T2T_SET_TAG_RO_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001790 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001791}
1792
1793/*******************************************************************************
1794**
1795** Function rw_t2t_handle_format_tag_rsp
1796**
1797** Description This function handles formating a type 2 tag
1798**
1799** Returns none
1800**
1801*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001802static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001803 uint8_t* p;
1804 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1805 tNFC_STATUS status = NFC_STATUS_FAILED;
1806 uint16_t version_no;
1807 const tT2T_INIT_TAG* p_ret;
1808 uint8_t tms;
1809 uint8_t next_block = T2T_FIRST_DATA_BLOCK + 1;
1810 uint16_t addr, locked_area;
1811 bool b_notify = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001812
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001813 p = p_t2t->ndef_final_block;
1814 UINT8_TO_BE_STREAM(p, p_t2t->tlv_value[2]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001815
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001816 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001817 case RW_T2T_SUBSTATE_WAIT_READ_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001818 /* Start format operation */
1819 status = rw_t2t_format_tag();
1820 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001821
1822 case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1823
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001824 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1825 p_t2t->b_read_data = true;
1826 version_no = (uint16_t)p_data[0] << 8 | p_data[1];
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001827 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no);
1828 if (p_ret != NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001829 /* Valid Version Number */
1830 if (p_ret->b_calc_cc) /* Calculate tag size from Version Information */
1831 tms = rw_t2t_get_tag_size(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001832
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001833 else
1834 /* Tag size from Look up table */
1835 tms = p_ret->tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001836
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001837 /* Set CC with the Tag size from look up table or from calculated value
1838 */
1839 status = rw_t2t_set_cc(tms);
1840 }
1841 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001842
1843 case RW_T2T_SUBSTATE_WAIT_SET_CC:
1844
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001845 version_no = (uint16_t)p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1846 if ((version_no == 0) ||
1847 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) ==
1848 NULL) ||
1849 (!p_ret->b_multi_version) || (!p_ret->b_calc_cc)) {
1850 /* Currently Formating a non blank tag or a blank tag with manufacturer
1851 * has only one variant of tag. Set Null NDEF TLV and complete Format
1852 * Operation */
1853 next_block = T2T_FIRST_DATA_BLOCK;
1854 p = p_t2t->ndef_final_block;
1855 } else {
1856 addr = (uint16_t)(
1857 ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1858 ((uint16_t)p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) +
1859 T2T_STATIC_SIZE);
1860 locked_area = ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1861 ((uint16_t)p_t2t->tag_data[6]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001862
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001863 status = rw_t2t_set_lock_tlv(addr, p_t2t->tag_data[7], locked_area);
1864 if (status == NFC_STATUS_REJECTED) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001865 /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format
1866 * Operation */
1867 next_block = T2T_FIRST_DATA_BLOCK;
1868 p = p_t2t->ndef_final_block;
1869 } else
1870 break;
1871 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001872
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001873 /* falls through */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001874 case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
1875
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001876 /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
1877 UINT8_TO_BE_STREAM(p, TAG_NDEF_TLV);
1878 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001879
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001880 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1881 (!p_ret->b_otp)) {
1882 UINT8_TO_BE_STREAM(p, TAG_TERMINATOR_TLV);
1883 } else
1884 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001885
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001886 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
1887 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001888 status = rw_t2t_write(next_block, p_t2t->ndef_final_block);
1889 if (status == NFC_STATUS_OK) p_t2t->b_read_data = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001890 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001891
1892 case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001893 /* Tag Formated successfully */
1894 status = NFC_STATUS_OK;
1895 b_notify = true;
1896 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001897
1898 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001899 break;
1900 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001901
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001902 if (status != NFC_STATUS_OK || b_notify) {
1903 /* Notify upper layer the result of Format op */
Myles Watson1361d522017-09-26 13:39:54 -07001904 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001905 evt.status = status;
1906 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001907 (*rw_cb.p_cback)(RW_T2T_FORMAT_CPLT_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001908 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001909}
1910
1911/*******************************************************************************
1912**
1913** Function rw_t2t_update_attributes
1914**
1915** Description This function will update attribute for the current segment
1916** based on lock and reserved bytes
1917**
1918** Returns None
1919**
1920*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001921static void rw_t2t_update_attributes(void) {
1922 uint8_t count = 0;
1923 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1924 uint16_t lower_offset;
1925 uint16_t upper_offset;
1926 uint16_t offset;
1927 uint8_t num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001928
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001929 /* Prepare attr for the current segment */
1930 memset(p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001931
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001932 /* calculate offset where the current segment starts in the tag */
1933 lower_offset = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
1934 /* calculate offset where the current segment ends in the tag */
1935 upper_offset = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001936
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001937 /* check offset of lock bytes in the tag and update p_t2t->attr
1938 * for every lock byte that is present in the current segment */
1939 count = 0;
1940 while (count < p_t2t->num_lockbytes) {
1941 offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset +
1942 p_t2t->lockbyte[count].byte_index;
1943 if (offset >= lower_offset && offset < upper_offset) {
1944 /* Calculate offset in the current segment as p_t2t->attr is prepared for
1945 * one segment only */
1946 offset %= RW_T2T_SEGMENT_BYTES;
1947 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1948 * lock/reserved byte or not
1949 * So, each array element in p_t2t->attr covers two blocks in the tag as
1950 * T2 block size is 4 and array element size is 8
1951 * Set the corresponding bit in attr to indicate - reserved byte */
1952 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1953 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001954 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001955 count++;
1956 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001957
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001958 /* Search reserved bytes identified by all memory tlvs present in the tag */
1959 count = 0;
1960 while (count < p_t2t->num_mem_tlvs) {
1961 /* check the offset of reserved bytes in the tag and update p_t2t->attr
1962 * for every reserved byte that is present in the current segment */
1963 num_bytes = 0;
1964 while (num_bytes < p_t2t->mem_tlv[count].num_bytes) {
1965 offset = p_t2t->mem_tlv[count].offset + num_bytes;
1966 if (offset >= lower_offset && offset < upper_offset) {
1967 /* Let offset represents offset in the current segment as p_t2t->attr is
1968 * prepared for one segment only */
1969 offset %= RW_T2T_SEGMENT_BYTES;
1970 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1971 * lock/reserved byte or not
1972 * So, each array element in p_t2t->attr covers two blocks in the tag as
1973 * T2 block size is 4 and array element size is 8
1974 * Set the corresponding bit in attr to indicate - reserved byte */
1975 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1976 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
1977 }
1978 num_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001979 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001980 count++;
1981 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001982}
1983
1984/*******************************************************************************
1985**
1986** Function rw_t2t_get_lock_bits_for_segment
1987**
1988** Description This function returns the offset of lock bits associated for
1989** the specified segment
1990**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001991** Parameters: segment: The segment number to which lock bits are
1992** associated
1993** p_start_byte: The offset of lock byte that contains the
1994** first lock bit for the segment
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001995** p_start_bit: The offset of the lock bit in the lock byte
1996**
1997** p_end_byte: The offset of the last bit associcated to the
1998** segment
1999**
2000** Returns Total number of lock bits assigned to the specified segment
2001**
2002*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002003static uint8_t rw_t2t_get_lock_bits_for_segment(uint8_t segment,
2004 uint8_t* p_start_byte,
2005 uint8_t* p_start_bit,
2006 uint8_t* p_end_byte) {
2007 uint8_t total_bits = 0;
2008 uint16_t byte_count = 0;
2009 uint16_t lower_offset, upper_offset;
2010 uint8_t num_dynamic_locks = 0;
2011 uint8_t bit_count = 0;
2012 uint8_t bytes_locked_per_bit;
2013 uint8_t num_bits;
2014 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2015 bool b_all_bits_are_locks = true;
2016 uint16_t tag_size;
2017 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002018
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002019 tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
2020 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002021
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002022 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2023 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002024
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002025 lower_offset = segment * RW_T2T_SEGMENT_BYTES;
2026 if (segment == 0) {
2027 lower_offset += T2T_STATIC_SIZE;
2028 }
2029 upper_offset = (segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002030
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002031 byte_count = T2T_STATIC_SIZE;
2032 if (tag_size < upper_offset) {
2033 upper_offset = tag_size;
2034 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002035
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002036 *p_start_byte = num_dynamic_locks;
2037 *p_start_bit = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002038
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002039 while ((byte_count <= lower_offset) &&
2040 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2041 bytes_locked_per_bit =
2042 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2043 .bytes_locked_per_bit;
2044 /* Number of bits in the current lock byte */
2045 b_all_bits_are_locks =
2046 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2047 TAG_BITS_PER_BYTE <=
2048 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2049 .num_bits);
2050 num_bits =
2051 b_all_bits_are_locks
2052 ? TAG_BITS_PER_BYTE
2053 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2054 .num_bits %
2055 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002056
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002057 if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset) {
2058 /* Skip this lock byte as it covers different segment */
2059 byte_count += bytes_locked_per_bit * num_bits;
2060 num_dynamic_locks++;
2061 } else {
2062 bit_count = 0;
2063 while (bit_count < num_bits) {
2064 byte_count += bytes_locked_per_bit;
2065 if (byte_count > lower_offset) {
2066 /* First lock bit that is used to lock this segment */
2067 *p_start_byte = num_dynamic_locks;
2068 *p_end_byte = num_dynamic_locks;
2069 *p_start_bit = bit_count;
2070 bit_count++;
2071 total_bits = 1;
2072 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002073 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002074 bit_count++;
2075 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002076 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002077 }
2078 if (num_dynamic_locks == p_t2t->num_lockbytes) {
2079 return 0;
2080 }
2081 while ((byte_count < upper_offset) &&
2082 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2083 bytes_locked_per_bit =
2084 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2085 .bytes_locked_per_bit;
2086 /* Number of bits in the current lock byte */
2087 b_all_bits_are_locks =
2088 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2089 TAG_BITS_PER_BYTE <=
2090 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2091 .num_bits);
2092 num_bits =
2093 b_all_bits_are_locks
2094 ? TAG_BITS_PER_BYTE
2095 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2096 .num_bits %
2097 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002098
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002099 if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count <
2100 upper_offset) {
2101 /* Collect all lock bits that covers the current segment */
2102 byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2103 total_bits += num_bits - bit_count;
2104 bit_count = 0;
2105 *p_end_byte = num_dynamic_locks;
2106 num_dynamic_locks++;
2107 } else {
2108 /* The last lock byte that covers the current segment */
2109 bit_count = 0;
2110 while (bit_count < num_bits) {
2111 /* The last lock bit that is used to lock this segment */
2112 byte_count += bytes_locked_per_bit;
2113 if (byte_count >= upper_offset) {
2114 *p_end_byte = num_dynamic_locks;
2115 total_bits += (bit_count + 1);
2116 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002117 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002118 bit_count++;
2119 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002120 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002121 }
2122 return total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002123}
2124
2125/*******************************************************************************
2126**
2127** Function rw_t2t_update_lock_attributes
2128**
2129** Description This function will check if the tag index passed as
2130** argument is a locked byte and return TRUE or FALSE
2131**
2132** Parameters: index, the index of the byte in the tag
2133**
2134**
2135** Returns TRUE, if the specified index in the tag is a locked or
2136** reserved or otp byte
2137** FALSE, otherwise
2138**
2139*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002140static void rw_t2t_update_lock_attributes(void) {
2141 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2142 uint8_t xx = 0;
2143 uint8_t num_static_lock_bytes = 0;
2144 uint8_t num_dyn_lock_bytes = 0;
2145 uint8_t bits_covered = 0;
2146 uint8_t bytes_covered = 0;
2147 uint8_t block_count = 0;
2148 bool b_all_bits_are_locks = true;
2149 uint8_t bytes_locked_per_lock_bit;
2150 uint8_t start_lock_byte;
2151 uint8_t start_lock_bit;
2152 uint8_t end_lock_byte;
2153 uint8_t num_lock_bits;
2154 uint8_t total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002155
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002156 /* Prepare lock_attr for the current segment */
2157 memset(p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002158
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002159 block_count = 0;
2160 if (p_t2t->segment == 0) {
2161 /* Update lock_attributes based on static lock bytes */
2162 xx = 0;
2163 num_static_lock_bytes = 0;
2164 block_count = 0;
2165 num_lock_bits =
2166 TAG_BITS_PER_BYTE - 1; /* the inner while loop increases xx by 2. need
2167 (-1) to avoid coverity overrun error */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002168
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002169 while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES) {
2170 /* Update lock attribute based on 2 static locks */
2171 while (xx < num_lock_bits) {
2172 p_t2t->lock_attr[block_count] = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002173
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002174 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2175 rw_t2t_mask_bits[xx++]) {
2176 /* If the bit is set then 1 block is locked */
2177 p_t2t->lock_attr[block_count] = 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002178 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002179
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002180 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2181 rw_t2t_mask_bits[xx++]) {
2182 /* If the bit is set then 1 block is locked */
2183 p_t2t->lock_attr[block_count] |= 0xF0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002184 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002185 block_count++;
2186 }
2187 num_static_lock_bytes++;
2188 xx = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002189 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002190 /* UID is always locked, irrespective of the lock value */
2191 p_t2t->lock_attr[0x00] = 0xFF;
2192 }
2193
2194 /* Get lock bits applicable for the current segment */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002195 total_bits = rw_t2t_get_lock_bits_for_segment(
2196 p_t2t->segment, &start_lock_byte, &start_lock_bit, &end_lock_byte);
2197 if (total_bits != 0) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002198 /* update lock_attributes based on current segment using dynamic lock bytes
2199 */
2200 xx = start_lock_bit;
2201 num_dyn_lock_bytes = start_lock_byte;
2202 bits_covered = 0;
2203 bytes_covered = 0;
2204 num_lock_bits = TAG_BITS_PER_BYTE;
2205 p_t2t->lock_attr[block_count] = 0;
2206
2207 while (num_dyn_lock_bytes <= end_lock_byte) {
2208 bytes_locked_per_lock_bit =
2209 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2210 .bytes_locked_per_bit;
2211 /* Find number of bits in the byte are lock bits */
2212 b_all_bits_are_locks =
2213 ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) *
2214 TAG_BITS_PER_BYTE <=
2215 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2216 .num_bits);
2217 num_lock_bits =
2218 b_all_bits_are_locks
2219 ? TAG_BITS_PER_BYTE
2220 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2221 .num_bits %
2222 TAG_BITS_PER_BYTE;
2223
2224 while (xx < num_lock_bits) {
2225 bytes_covered = 0;
2226 while (bytes_covered < bytes_locked_per_lock_bit) {
2227 if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte &
2228 rw_t2t_mask_bits[xx]) {
2229 /* If the bit is set then it is locked */
2230 p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
2231 }
2232 bytes_covered++;
2233 bits_covered++;
2234 if (bits_covered == TAG_BITS_PER_BYTE) {
2235 /* Move to next 8 bytes */
2236 bits_covered = 0;
2237 block_count++;
2238 /* Assume unlocked before updating using locks */
2239 if (block_count < RW_T2T_SEGMENT_SIZE)
2240 p_t2t->lock_attr[block_count] = 0;
2241 }
2242 }
2243 xx++;
2244 }
2245 num_dyn_lock_bytes++;
2246 xx = 0;
2247 }
2248 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002249}
2250
2251/*******************************************************************************
2252**
2253** Function rw_t2t_is_lock_res_byte
2254**
2255** Description This function will check if the tag index passed as
2256** argument is a lock or reserved or otp byte and return
2257** TRUE or FALSE
2258**
2259** Parameters: index, the index of the byte in the tag
2260**
2261**
2262** Returns TRUE, if the specified index in the tag is a locked or
2263** reserved or otp byte
2264** FALSE, otherwise
2265**
2266*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002267static bool rw_t2t_is_lock_res_byte(uint16_t index) {
2268 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002269
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002270 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002271
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002272 if (p_t2t->attr_seg != p_t2t->segment) {
2273 /* Update attributes for the current segment */
2274 rw_t2t_update_attributes();
2275 p_t2t->attr_seg = p_t2t->segment;
2276 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002277
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002278 index = index % RW_T2T_SEGMENT_BYTES;
2279 /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a
2280 * lock/reserved byte or not
2281 * So, each array element in p_t2t->attr covers two blocks in the tag as T2
2282 * block size is 4 and array element size is 8
2283 * Find the block and offset for the index (passed as argument) and Check if
2284 * the offset bit in the
2285 * p_t2t->attr[block/2] is set or not. If the bit is set then it is a
2286 * lock/reserved byte, otherwise not */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002287
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002288 return ((p_t2t->attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0) ? false
2289 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002290}
2291
2292/*******************************************************************************
2293**
2294** Function rw_t2t_is_read_only_byte
2295**
2296** Description This function will check if the tag index passed as
2297** argument is a locked and return
2298** TRUE or FALSE
2299**
2300** Parameters: index, the index of the byte in the tag
2301**
2302**
2303** Returns TRUE, if the specified index in the tag is a locked or
2304** reserved or otp byte
2305** FALSE, otherwise
2306**
2307*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002308static bool rw_t2t_is_read_only_byte(uint16_t index) {
2309 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002310
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002311 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002312
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002313 if (p_t2t->lock_attr_seg != p_t2t->segment) {
2314 /* Update lock attributes for the current segment */
2315 rw_t2t_update_lock_attributes();
2316 p_t2t->lock_attr_seg = p_t2t->segment;
2317 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002318
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002319 index = index % RW_T2T_SEGMENT_BYTES;
2320 /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a
2321 * read only byte or read write byte
2322 * So, each array element in p_t2t->lock_attr covers two blocks of the tag as
2323 * T2 block size is 4 and array element size is 8
2324 * Find the block and offset for the index (passed as argument) and Check if
2325 * the offset bit in
2326 * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a
2327 * read only byte, otherwise read write byte */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002328
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002329 return ((p_t2t->lock_attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0)
2330 ? false
2331 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002332}
2333
2334/*******************************************************************************
2335**
2336** Function rw_t2t_set_dynamic_lock_bits
2337**
2338** Description This function will set dynamic lock bits as part of
2339** configuring tag as read only
2340**
2341** Returns
2342** NFC_STATUS_OK, Command sent to set dynamic lock bits
2343** NFC_STATUS_FAILED: otherwise
2344**
2345*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002346tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data) {
2347 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2348 uint8_t write_block[T2T_BLOCK_SIZE];
2349 uint16_t offset;
2350 uint16_t next_offset;
2351 uint8_t num_bits;
2352 uint8_t next_num_bits;
2353 tNFC_STATUS status = NFC_STATUS_FAILED;
2354 uint8_t num_locks;
2355 uint8_t lock_count;
2356 bool b_all_bits_are_locks = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002357
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002358 num_locks = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002359
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002360 memcpy(write_block, p_data, T2T_BLOCK_SIZE);
2361 while (num_locks < p_t2t->num_lockbytes) {
2362 if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
2363 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
2364 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002365
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002366 /* Check if all bits are lock bits in the byte */
2367 b_all_bits_are_locks =
2368 ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <=
2369 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2370 num_bits =
2371 b_all_bits_are_locks
2372 ? TAG_BITS_PER_BYTE
2373 : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits %
2374 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002375
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002376 write_block[(uint8_t)(offset % T2T_BLOCK_SIZE)] |=
2377 tags_pow(2, num_bits) - 1;
2378 lock_count = num_locks + 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002379
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002380 /* Set all the lock bits in the block using a sing block write command */
2381 while (lock_count < p_t2t->num_lockbytes) {
2382 next_offset =
2383 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset +
2384 p_t2t->lockbyte[lock_count].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002385
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002386 /* Check if all bits are lock bits in the byte */
2387 b_all_bits_are_locks =
2388 ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <=
2389 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2390 next_num_bits =
2391 b_all_bits_are_locks
2392 ? TAG_BITS_PER_BYTE
2393 : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index]
2394 .num_bits %
2395 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002396
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002397 if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE) {
2398 write_block[(uint8_t)(next_offset % T2T_BLOCK_SIZE)] |=
2399 tags_pow(2, next_num_bits) - 1;
2400 } else
2401 break;
2402 lock_count++;
2403 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002404
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002405 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2406 /* send WRITE command to set dynamic lock bits */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002407 status = rw_t2t_write((uint16_t)(offset / T2T_BLOCK_SIZE), write_block);
2408 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002409 while (lock_count > num_locks) {
2410 /* Set update initiated flag to indicate a write command is sent to
2411 * set dynamic lock bits of the block */
2412 p_t2t->lockbyte[lock_count - 1].lock_status =
2413 RW_T2T_LOCK_UPDATE_INITIATED;
2414 lock_count--;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002415 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002416 } else
2417 status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002418
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002419 break;
2420 }
2421 num_locks++;
2422 }
2423
2424 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002425}
2426
2427/*******************************************************************************
2428**
2429** Function rw_t2t_set_lock_tlv
2430**
2431** Description This function will set lock control tlv on the blank
2432** activated type 2 tag based on values read from version block
2433**
2434** Parameters: TAG data memory size
2435**
2436** Returns
2437** NFC_STATUS_OK, Command sent to set Lock TLV
2438** NFC_STATUS_FAILED: otherwise
2439**
2440*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002441tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
2442 uint16_t locked_area_size) {
2443 tNFC_STATUS status = NFC_STATUS_FAILED;
2444 int8_t PageAddr = 0;
2445 int8_t BytePerPage = 0;
2446 int8_t ByteOffset = 0;
2447 uint8_t a;
2448 uint8_t data_block[T2T_BLOCK_SIZE];
2449 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2450 uint8_t* p;
2451 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002452
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002453 for (xx = 15; xx > 0; xx--) {
2454 a = (uint8_t)(addr / xx);
2455 a += (addr % xx) ? 1 : 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002456
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002457 BytePerPage = (int8_t)tags_log2(a);
2458 ByteOffset = (int8_t)(addr - xx * tags_pow(2, BytePerPage));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002459
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002460 if (ByteOffset < 16) {
2461 PageAddr = xx;
2462 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002463 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002464 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002465
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002466 if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16)) {
2467 memset(data_block, 0, T2T_BLOCK_SIZE);
2468 p = data_block;
2469 UINT8_TO_BE_STREAM(p, T2T_TLV_TYPE_LOCK_CTRL);
2470 UINT8_TO_BE_STREAM(p, T2T_TLEN_LOCK_CTRL_TLV);
2471 UINT8_TO_BE_STREAM(p, (PageAddr << 4 | ByteOffset));
2472 UINT8_TO_BE_STREAM(p, num_dyn_lock_bits);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002473
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002474 p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2475 p_t2t->tlv_value[1] = num_dyn_lock_bits;
2476 p_t2t->tlv_value[2] =
2477 (uint8_t)(BytePerPage << 4 | tags_log2(locked_area_size));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002478
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002479 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002480
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002481 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002482 status = rw_t2t_write(T2T_FIRST_DATA_BLOCK, data_block);
2483 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002484 p_t2t->b_read_data = false;
2485 } else
2486 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2487 } else
2488 status = NFC_STATUS_REJECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002489
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002490 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002491}
2492
2493/*******************************************************************************
2494**
2495** Function rw_t2t_set_cc
2496**
2497** Description This function will set Capability Container on the activated
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002498** type 2 tag with default values of CC0, CC1, CC4 and
2499** specified CC3 value
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002500**
2501** Parameters: CC3 value of the tag
2502**
2503** Returns
2504** NFC_STATUS_OK, Command sent to set CC
2505** NFC_STATUS_FAILED: otherwise
2506**
2507*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002508tNFC_STATUS rw_t2t_set_cc(uint8_t tms) {
2509 uint8_t cc_block[T2T_BLOCK_SIZE];
2510 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2511 tNFC_STATUS status = NFC_STATUS_FAILED;
2512 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002513
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002514 memset(cc_block, 0, T2T_BLOCK_SIZE);
2515 memset(p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2516 p = cc_block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002517
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002518 /* Prepare Capability Container */
2519 UINT8_TO_BE_STREAM(p, T2T_CC0_NMN);
2520 UINT8_TO_BE_STREAM(p, T2T_CC1_VNO);
2521 UINT8_TO_BE_STREAM(p, tms);
2522 UINT8_TO_BE_STREAM(p, T2T_CC3_RWA_RW);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002523
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002524 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002525
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002526 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002527 status = rw_t2t_write(T2T_CC_BLOCK, cc_block);
2528 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002529 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2530 p_t2t->b_read_hdr = false;
2531 } else
2532 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002533
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002534 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002535}
2536
2537/*******************************************************************************
2538**
2539** Function rw_t2t_format_tag
2540**
2541** Description This function will format tag based on Manufacturer ID
2542**
2543** Returns
2544** NFC_STATUS_OK, Command sent to format Tag
2545** NFC_STATUS_FAILED: otherwise
2546**
2547*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002548tNFC_STATUS rw_t2t_format_tag(void) {
2549 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2550 const tT2T_INIT_TAG* p_ret;
2551 uint8_t tms;
2552 tNFC_STATUS status = NFC_STATUS_FAILED;
2553 bool b_blank_tag = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002554
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002555 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
2556 if (p_ret == NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002557 RW_TRACE_WARNING1(
2558 "rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the "
2559 "tag!",
2560 p_t2t->tag_hdr[0]);
2561 return (NFC_STATUS_FAILED);
2562 }
2563
2564 if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0) {
2565 /* If OTP tag has valid NDEF Message, cannot format the tag */
2566 if ((p_t2t->ndef_msg_len > 0) && (p_ret->b_otp)) {
2567 RW_TRACE_WARNING0(
2568 "rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2569 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002570 }
2571
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002572 if (((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) &&
2573 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) ||
2574 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) &&
2575 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
2576 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
2577 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
2578 RW_TRACE_WARNING0("rw_t2t_format_tag - Tag not blank to Format!");
2579 return (NFC_STATUS_FAILED);
2580 } else {
2581 tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2582 b_blank_tag = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002583 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002584 } else
2585 tms = p_ret->tms;
2586
2587 memset(p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2588
2589 if (!b_blank_tag || !p_ret->b_multi_version) {
2590 status = rw_t2t_set_cc(tms);
2591 } else if (p_ret->version_block != 0) {
2592 /* If Version number is not read, READ it now */
2593 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2594
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002595 status = rw_t2t_read(p_ret->version_block);
2596 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002597 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002598 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002599 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2600 } else {
2601 /* UID block is the version block */
2602 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2603 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2604 rw_t2t_handle_format_tag_rsp(p_t2t->tag_hdr);
2605 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002606
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002607 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002608}
2609
2610/*******************************************************************************
2611**
2612** Function rw_t2t_soft_lock_tag
2613**
2614** Description This function will soft lock the tag after validating CC.
2615**
2616** Returns
2617** NFC_STATUS_OK, Command sent to soft lock the tag
2618** NFC_STATUS_FAILED: otherwise
2619**
2620*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002621tNFC_STATUS rw_t2t_soft_lock_tag(void) {
2622 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2623 tNFC_STATUS status = NFC_STATUS_FAILED;
2624 uint8_t write_block[T2T_BLOCK_SIZE];
2625 uint8_t num_locks;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002626
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002627 /* If CC block is read and cc3 is soft locked, reject the command */
2628 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO) {
2629 RW_TRACE_ERROR1(
2630 "rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: "
2631 "%u",
2632 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2633 return (NFC_STATUS_FAILED);
2634 }
2635
2636 if (p_t2t->b_hard_lock) {
2637 /* Should have performed NDEF Detection on dynamic memory structure tag,
2638 * before permanently converting to Read only
2639 * Even when no lock control tlv is present, default lock bytes should be
2640 * present */
2641
2642 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) &&
2643 (p_t2t->num_lockbytes == 0)) {
2644 RW_TRACE_ERROR0(
2645 "rw_t2t_soft_lock_tag: Error: Lock TLV not detected! Cannot hard "
2646 "lock the tag");
2647 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002648 }
2649
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002650 /* On dynamic memory structure tag, reset all lock bytes status to 'Not
2651 * Updated' if not in Updated status */
2652 num_locks = 0;
2653 while (num_locks < p_t2t->num_lockbytes) {
2654 if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2655 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2656 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002657 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002658 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002659
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002660 memcpy(write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2661 write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002662
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002663 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2664 /* First Soft lock the tag */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002665 status = rw_t2t_write(T2T_CC_BLOCK, write_block);
2666 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002667 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
2668 p_t2t->b_read_hdr = false;
2669 } else {
2670 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2671 }
2672 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002673}
2674
2675/*****************************************************************************
2676**
2677** Function RW_T2tFormatNDef
2678**
2679** Description
2680** Format Tag content
2681**
2682** Returns
2683** NFC_STATUS_OK, Command sent to format Tag
2684** NFC_STATUS_FAILED: otherwise
2685**
2686*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002687tNFC_STATUS RW_T2tFormatNDef(void) {
2688 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2689 tNFC_STATUS status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002690
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002691 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2692 RW_TRACE_WARNING1("RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u",
2693 p_t2t->state);
2694 return (NFC_STATUS_FAILED);
2695 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002696
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002697 if (!p_t2t->b_read_hdr) {
2698 /* If UID is not read, READ it now */
2699 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002700
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002701 status = rw_t2t_read(0);
2702 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002703 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002704 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002705 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2706 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002707 status = rw_t2t_format_tag();
2708 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002709 }
2710 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002711}
2712
2713/*******************************************************************************
2714**
2715** Function RW_T2tLocateTlv
2716**
2717** Description This function is used to perform TLV detection on a Type 2
2718** tag, and retrieve the tag's TLV attribute information.
2719**
2720** Before using this API, the application must call
2721** RW_SelectTagType to indicate that a Type 2 tag has been
2722** activated.
2723**
2724** Parameters: tlv_type : TLV to detect
2725**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002726** Returns NCI_STATUS_OK, if detection was started. Otherwise, error
2727** status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002728**
2729*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002730tNFC_STATUS RW_T2tLocateTlv(uint8_t tlv_type) {
2731 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2732 tNFC_STATUS status;
2733 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002734
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002735 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2736 RW_TRACE_ERROR1("Error: Type 2 tag not activated or Busy - State: %u",
2737 p_t2t->state);
2738 return (NFC_STATUS_BUSY);
2739 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002740
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002741 if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) &&
2742 (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV)) {
2743 RW_TRACE_API1("RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
2744 return (NFC_STATUS_FAILED);
2745 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002746
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002747 if ((tlv_type == TAG_LOCK_CTRL_TLV) && (p_t2t->b_read_hdr) &&
2748 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)) {
2749 p_t2t->b_read_hdr = false;
2750 RW_TRACE_API1(
2751 "RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x",
2752 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2753 return (NFC_STATUS_FAILED);
2754 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002755
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002756 if ((tlv_type == TAG_NDEF_TLV) && (p_t2t->b_read_hdr) &&
2757 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) {
2758 p_t2t->b_read_hdr = false;
2759 RW_TRACE_WARNING3(
2760 "RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: "
2761 "0x%02x, CC[3]: 0x%02x",
2762 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
2763 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2764 return (NFC_STATUS_FAILED);
2765 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002766
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002767 p_t2t->work_offset = 0;
2768 p_t2t->tlv_detect = tlv_type;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002769
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002770 /* Reset control block variables based on type of tlv to detect */
2771 if (tlv_type == TAG_LOCK_CTRL_TLV) {
2772 p_t2t->num_lockbytes = 0;
2773 p_t2t->num_lock_tlvs = 0;
2774 } else if (tlv_type == TAG_MEM_CTRL_TLV) {
2775 p_t2t->num_mem_tlvs = 0;
2776 } else if (tlv_type == TAG_NDEF_TLV) {
2777 p_t2t->ndef_msg_offset = 0;
2778 p_t2t->num_lockbytes = 0;
2779 p_t2t->num_lock_tlvs = 0;
2780 p_t2t->num_mem_tlvs = 0;
2781 p_t2t->ndef_msg_len = 0;
2782 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
2783 } else {
2784 p_t2t->prop_msg_len = 0;
2785 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002786
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002787 if (!p_t2t->b_read_hdr) {
2788 /* First read CC block */
2789 block = 0;
2790 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2791 } else {
2792 /* Read first data block */
2793 block = T2T_FIRST_DATA_BLOCK;
2794 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2795 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002796
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002797 /* Start reading tag, looking for the specified TLV */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002798 status = rw_t2t_read((uint16_t)block);
2799 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002800 p_t2t->state = RW_T2T_STATE_DETECT_TLV;
2801 } else {
2802 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2803 }
2804 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002805}
2806
2807/*******************************************************************************
2808**
2809** Function RW_T2tDetectNDef
2810**
2811** Description This function is used to perform NDEF detection on a Type 2
2812** tag, and retrieve the tag's NDEF attribute information.
2813**
2814** Before using this API, the application must call
2815** RW_SelectTagType to indicate that a Type 2 tag has been
2816** activated.
2817**
2818** Parameters: none
2819**
2820** Returns NCI_STATUS_OK,if detect op started.Otherwise,error status.
2821**
2822*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002823tNFC_STATUS RW_T2tDetectNDef(bool skip_dyn_locks) {
2824 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Evan Chuc95c79c2013-04-12 17:38:09 -04002825
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002826 p_t2t->skip_dyn_locks = skip_dyn_locks;
Evan Chuc95c79c2013-04-12 17:38:09 -04002827
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002828 return RW_T2tLocateTlv(TAG_NDEF_TLV);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002829}
2830
2831/*******************************************************************************
2832**
2833** Function RW_T2tReadNDef
2834**
2835** Description Retrieve NDEF contents from a Type2 tag.
2836**
2837** The RW_T2T_NDEF_READ_EVT event is used to notify the
2838** application after reading the NDEF message.
2839**
2840** Before using this API, the RW_T2tDetectNDef function must
2841** be called to verify that the tag contains NDEF data, and to
2842** retrieve the NDEF attributes.
2843**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002844** Internally, this command will be separated into multiple
2845** Tag2 Read commands (if necessary) - depending on the NDEF
2846** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002847**
2848** Parameters: p_buffer: The buffer into which to read the NDEF message
2849** buf_len: The length of the buffer
2850**
2851** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
2852**
2853*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002854tNFC_STATUS RW_T2tReadNDef(uint8_t* p_buffer, uint16_t buf_len) {
2855 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2856 tNFC_STATUS status = NFC_STATUS_OK;
2857 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002858
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002859 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2860 RW_TRACE_ERROR1("Error: Type 2 tag not activated or Busy - State: %u",
2861 p_t2t->state);
2862 return (NFC_STATUS_FAILED);
2863 }
2864
2865 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
2866 RW_TRACE_ERROR0("RW_T2tReadNDef - Error: NDEF detection not performed yet");
2867 return (NFC_STATUS_FAILED);
2868 }
2869
2870 if (buf_len < p_t2t->ndef_msg_len) {
2871 RW_TRACE_WARNING2(
2872 "RW_T2tReadNDef - buffer size: %u less than NDEF msg sise: %u",
2873 buf_len, p_t2t->ndef_msg_len);
2874 return (NFC_STATUS_FAILED);
2875 }
2876
2877 if (!p_t2t->ndef_msg_len) {
2878 RW_TRACE_WARNING1("RW_T2tReadNDef - NDEF Message length is zero ",
2879 p_t2t->ndef_msg_len);
2880 return (NFC_STATUS_NOT_INITIALIZED);
2881 }
2882
2883 p_t2t->p_ndef_buffer = p_buffer;
2884 p_t2t->work_offset = 0;
2885
2886 block = (uint16_t)(p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
2887 block -= block % T2T_READ_BLOCKS;
2888
2889 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2890
2891 if ((block == T2T_FIRST_DATA_BLOCK) && (p_t2t->b_read_data)) {
2892 p_t2t->state = RW_T2T_STATE_READ_NDEF;
2893 p_t2t->block_read = T2T_FIRST_DATA_BLOCK;
2894 rw_t2t_handle_ndef_read_rsp(p_t2t->tag_data);
2895 } else {
2896 /* Start reading NDEF Message */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002897 status = rw_t2t_read(block);
2898 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002899 p_t2t->state = RW_T2T_STATE_READ_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002900 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002901 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002902
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002903 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002904}
2905
2906/*******************************************************************************
2907**
2908** Function RW_T2tWriteNDef
2909**
2910** Description Write NDEF contents to a Type2 tag.
2911**
2912** Before using this API, the RW_T2tDetectNDef
2913** function must be called to verify that the tag contains
2914** NDEF data, and to retrieve the NDEF attributes.
2915**
2916** The RW_T2T_NDEF_WRITE_EVT callback event will be used to
2917** notify the application of the response.
2918**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002919** Internally, this command will be separated into multiple
2920** Tag2 Write commands (if necessary) - depending on the NDEF
2921** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002922**
2923** Parameters: msg_len: The length of the buffer
2924** p_msg: The NDEF message to write
2925**
2926** Returns NCI_STATUS_OK,if write was started. Otherwise, error status
2927**
2928*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002929tNFC_STATUS RW_T2tWriteNDef(uint16_t msg_len, uint8_t* p_msg) {
2930 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2931 uint16_t block;
2932 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002933
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002934 tNFC_STATUS status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002935
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002936 if (p_t2t->state != RW_T2T_STATE_IDLE) {
2937 RW_TRACE_ERROR1("Error: Type 2 tag not activated or Busy - State: %u",
2938 p_t2t->state);
2939 return (NFC_STATUS_FAILED);
2940 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002941
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002942 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
2943 RW_TRACE_ERROR0("RW_T2tWriteNDef - Error: NDEF detection not performed!");
2944 return (NFC_STATUS_FAILED);
2945 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002946
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002947 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) {
2948 RW_TRACE_ERROR1("RW_T2tWriteNDef - Write access not granted - CC3: %u",
2949 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2950 return (NFC_STATUS_REFUSED);
2951 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002952
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002953 /* Check if there is enough memory on the tag */
2954 if (msg_len > p_t2t->max_ndef_msg_len) {
2955 RW_TRACE_ERROR1(
2956 "RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes",
2957 p_t2t->max_ndef_msg_len);
2958 return (NFC_STATUS_FAILED);
2959 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002960
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002961 /* If OTP tag and tag has valid NDEF Message, stop writting new NDEF Message
2962 * as it may corrupt the tag */
2963 if ((p_t2t->ndef_msg_len > 0) &&
2964 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
2965 (p_ret->b_otp)) {
2966 RW_TRACE_WARNING0(
2967 "RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
2968 return (NFC_STATUS_FAILED);
2969 }
2970 p_t2t->p_new_ndef_buffer = p_msg;
2971 p_t2t->new_ndef_msg_len = msg_len;
2972 p_t2t->work_offset = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002973
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002974 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
2975 /* Read first NDEF Block before updating NDEF */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002976
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002977 block = (uint16_t)(p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002978
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002979 if ((block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) &&
2980 (p_t2t->b_read_data)) {
2981 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
2982 p_t2t->block_read = block;
2983 rw_t2t_handle_ndef_write_rsp(
2984 &p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
2985 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002986 status = rw_t2t_read(block);
2987 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002988 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002989 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002990 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2991 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002992
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002993 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002994}
2995
2996/*******************************************************************************
2997**
2998** Function RW_T2tSetTagReadOnly
2999**
3000** Description This function can be called to set T2 tag as read only.
3001**
3002** Parameters: b_hard_lock: To indicate hard lock the tag or not
3003**
3004** Returns NCI_STATUS_OK, if setting tag as read only was started.
3005** Otherwise, error status.
3006**
3007*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003008tNFC_STATUS RW_T2tSetTagReadOnly(bool b_hard_lock) {
3009 tNFC_STATUS status = NFC_STATUS_FAILED;
3010 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003011
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003012 if (p_t2t->state != RW_T2T_STATE_IDLE) {
3013 RW_TRACE_ERROR1(
3014 "RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - "
3015 "State: %u",
3016 p_t2t->state);
3017 return (NFC_STATUS_FAILED);
3018 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003019
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003020 p_t2t->b_hard_lock = b_hard_lock;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003021
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003022 if (!p_t2t->b_read_hdr) {
3023 /* Read CC block before configuring tag as Read only */
3024 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003025 status = rw_t2t_read((uint16_t)0);
3026 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003027 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
3028 } else
3029 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3030 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003031 status = rw_t2t_soft_lock_tag();
3032 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003033 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003034
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003035 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003036}
3037
Ruchi Kandoi303fec12016-12-14 13:22:38 -08003038#endif /* (RW_NDEF_INCLUDED == TRUE) */