blob: c18c68513fb2312015926e86e0a46d772a378529 [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>
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080026
27#include <android-base/stringprintf.h>
28#include <base/logging.h>
Ruchi Kandoi183352b2018-09-21 14:04:22 -070029#include <log/log.h>
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080030
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080031#include "nfc_target.h"
32
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080033#include "nci_hmsgs.h"
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080034#include "nfc_api.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080035#include "rw_api.h"
36#include "rw_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080037
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080038using android::base::StringPrintf;
39
40extern bool nfc_debug_enabled;
41
Ruchi Kandoi303fec12016-12-14 13:22:38 -080042#if (RW_NDEF_INCLUDED == TRUE)
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080043
44/* Local static functions */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080045static void rw_t2t_handle_cc_read_rsp(void);
46static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data);
47static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data);
48static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data);
49static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data);
50static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data);
51static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data);
52static uint8_t rw_t2t_get_tag_size(uint8_t* p_data);
53static void rw_t2t_extract_default_locks_info(void);
54static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
55 bool b_update_len);
56static uint8_t rw_t2t_get_ndef_flags(void);
57static uint16_t rw_t2t_get_ndef_max_size(void);
58static tNFC_STATUS rw_t2t_read_locks(void);
59static tNFC_STATUS rw_t2t_read_ndef_last_block(void);
60static void rw_t2t_update_attributes(void);
61static void rw_t2t_update_lock_attributes(void);
62static bool rw_t2t_is_lock_res_byte(uint16_t index);
63static bool rw_t2t_is_read_only_byte(uint16_t index);
64static tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len,
65 bool b_update_len);
66static tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block,
67 uint16_t msg_len,
68 bool b_update_len);
69static tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block);
70static tNFC_STATUS rw_t2t_add_terminator_tlv(void);
71static bool rw_t2t_is_read_before_write_block(uint16_t block,
72 uint16_t* p_block_to_read);
73static tNFC_STATUS rw_t2t_set_cc(uint8_t tms);
74static tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
75 uint16_t locked_area_size);
76static tNFC_STATUS rw_t2t_format_tag(void);
77static tNFC_STATUS rw_t2t_soft_lock_tag(void);
78static tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data);
79static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080080
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080081const uint8_t rw_t2t_mask_bits[8] = {0x01, 0x02, 0x04, 0x08,
82 0x10, 0x20, 0x40, 0x80};
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080083
84/*******************************************************************************
85**
86** Function rw_t2t_handle_rsp
87**
88** Description This function handles response to command sent during
89** NDEF and other tlv operation
90**
91** Returns None
92**
93*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080094void rw_t2t_handle_rsp(uint8_t* p_data) {
95 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080096
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080097 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
98 p_t2t->b_read_hdr = true;
99 memcpy(p_t2t->tag_hdr, p_data, T2T_READ_DATA_LEN);
100 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800101
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800102 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800103 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800104 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
105 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
106 rw_t2t_handle_cc_read_rsp();
107 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
108 rw_t2t_handle_lock_read_rsp(p_data);
109 } else {
110 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800111 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800112 } else if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
113 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
114 if (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] == T2T_CC0_NMN) {
115 rw_t2t_handle_cc_read_rsp();
116 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700117 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800118 "NDEF Detection failed!, CC[0]: 0x%02x, CC[1]: 0x%02x, CC[3]: "
119 "0x%02x",
120 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE],
121 p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
122 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
123 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
124 }
125 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
126 rw_t2t_handle_lock_read_rsp(p_data);
127 } else {
128 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800129 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800130 } else {
131 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
132 rw_t2t_handle_cc_read_rsp();
133 } else {
134 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800135 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800136 }
137 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800138
139 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800140 rw_t2t_handle_config_tag_readonly(p_data);
141 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800142
143 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800144 rw_t2t_handle_format_tag_rsp(p_data);
145 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800146
147 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800148 rw_t2t_handle_ndef_read_rsp(p_data);
149 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800150
151 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800152 rw_t2t_handle_ndef_write_rsp(p_data);
153 break;
154 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800155}
156
157/*******************************************************************************
158**
159** Function rw_t2t_info_to_event
160**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800161** Description This function returns RW event code based on the current
162** state
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800163**
164** Returns RW event code
165**
166*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800167tRW_EVENT rw_t2t_info_to_event(const tT2T_CMD_RSP_INFO* p_info) {
168 tRW_EVENT rw_event;
169 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800170
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800171 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800172 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800173 if (p_t2t->tlv_detect == TAG_NDEF_TLV)
174 rw_event = RW_T2T_NDEF_DETECT_EVT;
175 else
176 rw_event = RW_T2T_TLV_DETECT_EVT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800177
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800178 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800179
180 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800181 rw_event = RW_T2T_NDEF_READ_EVT;
182 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800183
184 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800185 rw_event = RW_T2T_NDEF_WRITE_EVT;
186 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800187
188 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800189 rw_event = RW_T2T_SET_TAG_RO_EVT;
190 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800191
192 case RW_T2T_STATE_CHECK_PRESENCE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800193 rw_event = RW_T2T_PRESENCE_CHECK_EVT;
194 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800195
196 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800197 rw_event = RW_T2T_FORMAT_CPLT_EVT;
198 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800199
200 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800201 rw_event = t2t_info_to_evt(p_info);
202 break;
203 }
204 return rw_event;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800205}
206
207/*******************************************************************************
208**
209** Function rw_t2t_handle_cc_read_rsp
210**
211** Description Handle read cc bytes
212**
213** Returns none
214**
215*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800216static void rw_t2t_handle_cc_read_rsp(void) {
217 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800218
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800219 if (((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) &&
220 (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RO)) ||
221 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
222 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
223 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
224 /* Invalid Version number or RWA byte */
225 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
226 return;
227 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800228
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800229 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800230
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800231 if (rw_t2t_read((uint16_t)T2T_FIRST_DATA_BLOCK) != NFC_STATUS_OK) {
232 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
233 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800234}
235
236/*******************************************************************************
237**
238** Function rw_t2t_ntf_tlv_detect_complete
239**
240** Description Notify TLV detection complete to upper layer
241**
242** Returns none
243**
244*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800245static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status) {
246 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800247 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800248
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800249 if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
250 /* Notify upper layer the result of NDEF detect op */
Ruchi Kandoi9ba6d242017-10-13 16:07:01 -0700251 tRW_DETECT_NDEF_DATA ndef_data = {};
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800252 ndef_data.status = status;
253 ndef_data.protocol = NFC_PROTOCOL_T2T;
254 ndef_data.flags = rw_t2t_get_ndef_flags();
255 ndef_data.cur_size = p_t2t->ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800256
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800257 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_FORMATED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800258
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800259 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] == T2T_CC3_RWA_RW)
260 ndef_data.max_size = (uint32_t)rw_t2t_get_ndef_max_size();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800261 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800262 ndef_data.max_size = ndef_data.cur_size;
263
264 if (ndef_data.max_size < ndef_data.cur_size) {
265 ndef_data.flags |= RW_NDEF_FL_READ_ONLY;
266 ndef_data.max_size = ndef_data.cur_size;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800267 }
268
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800269 if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY)) {
270 ndef_data.flags |= RW_NDEF_FL_SOFT_LOCKABLE;
271 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_HARD_LOCKABLE;
272 }
273
274 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700275 tRW_DATA rw_data;
276 rw_data.ndef = ndef_data;
277 (*rw_cb.p_cback)(RW_T2T_NDEF_DETECT_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800278 } else if (p_t2t->tlv_detect == TAG_PROPRIETARY_TLV) {
Myles Watson1361d522017-09-26 13:39:54 -0700279 tRW_T2T_DETECT evt_data;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800280 evt_data.msg_len = p_t2t->prop_msg_len;
281 evt_data.status = status;
282 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700283 /* FIXME: Unsafe cast */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800284 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, (tRW_DATA*)&evt_data);
285 } else {
286 /* Notify upper layer the result of Lock/Mem TLV detect op */
Myles Watson1361d522017-09-26 13:39:54 -0700287 tRW_DETECT_TLV_DATA tlv_data;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800288 tlv_data.protocol = NFC_PROTOCOL_T2T;
289 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
290 tlv_data.num_bytes = p_t2t->num_lockbytes;
291 } else {
292 tlv_data.num_bytes = 0;
293 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++) {
294 tlv_data.num_bytes += p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes;
295 }
296 }
297 tlv_data.status = status;
298 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700299 tRW_DATA rw_data;
300 rw_data.tlv = tlv_data;
301 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800302 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800303}
304
305/*******************************************************************************
306**
307** Function rw_t2t_handle_lock_read_rsp
308**
309** Description Handle response to reading lock bytes
310**
311** Returns none
312**
313*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800314static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data) {
315 uint8_t updated_lock_byte;
316 uint8_t num_locks;
317 uint8_t offset = 0;
318 uint16_t lock_offset;
319 uint16_t base_lock_offset = 0;
320 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
321 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800322
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800323 /* Prepare NDEF/TLV attributes (based on current op) for sending response to
324 * upper layer */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800325
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800326 num_locks = 0;
327 updated_lock_byte = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800328
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800329 /* Extract all lock bytes present in the read 16 bytes
330 * but atleast one lock byte (base lock) should be present in the read 16
331 * bytes */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800332
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800333 while (num_locks < p_t2t->num_lockbytes) {
334 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
335 lock_offset =
336 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
337 p_t2t->lockbyte[num_locks].byte_index;
338 if (updated_lock_byte == 0) {
339 /* The offset of the first lock byte present in the 16 bytes read using
340 * READ command */
341 base_lock_offset = lock_offset;
342 /* Block number used to read may not be the block where lock offset is
343 * present */
344 offset = (uint8_t)(lock_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
345 /* Update the lock byte value in the control block */
346 p_t2t->lockbyte[num_locks].lock_byte = p_data[offset];
347 p_t2t->lockbyte[num_locks].b_lock_read = true;
348 updated_lock_byte++;
349 } else if (lock_offset > base_lock_offset) {
350 /* Atleast one lock byte will get updated in the control block */
351 if ((lock_offset - base_lock_offset + offset) < T2T_READ_DATA_LEN) {
352 /* And this lock byte is also present in the read data */
353 p_t2t->lockbyte[num_locks].lock_byte =
354 p_data[lock_offset - base_lock_offset + offset];
355 p_t2t->lockbyte[num_locks].b_lock_read = true;
356 updated_lock_byte++;
357 } else {
358 /* This lock byte is not present in the read data */
359 block = (uint16_t)(lock_offset / T2T_BLOCK_LEN);
360 block -= block % T2T_READ_BLOCKS;
361 /* send READ command to read this lock byte */
362 if (NFC_STATUS_OK != rw_t2t_read((uint16_t)block)) {
363 /* Unable to send Read command, notify failure status to upper layer
364 */
365 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
366 }
367 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800368 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800369 } else {
370 /* This Lock byte is not present in the read 16 bytes
371 * send READ command to read the lock byte */
372 if (NFC_STATUS_OK !=
373 rw_t2t_read((uint16_t)(lock_offset / T2T_BLOCK_LEN))) {
374 /* Unable to send Read command, notify failure status to upper layer
375 */
376 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
377 }
378 break;
379 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800380 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800381 num_locks++;
382 }
383 if (num_locks == p_t2t->num_lockbytes) {
384 /* All locks are read, notify upper layer */
385 rw_t2t_update_lock_attributes();
386 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_OK);
387 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800388}
389
390/*******************************************************************************
391**
392** Function rw_t2t_handle_tlv_detect_rsp
393**
394** Description Handle TLV detection.
395**
396** Returns none
397**
398*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800399static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data) {
400 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
401 uint16_t offset;
402 uint16_t len = 0;
403 bool failed = false;
404 bool found = false;
405 tRW_EVENT event;
406 uint8_t index;
407 uint8_t count = 0;
408 uint8_t xx;
409 tNFC_STATUS status;
410 tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
411 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
412 uint8_t tlvtype = p_t2t->tlv_detect;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800413
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800414 if (p_t2t->work_offset == 0) {
415 /* Skip UID,Static Lock block,CC*/
416 p_t2t->work_offset = T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN;
417 p_t2t->b_read_data = true;
418 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
419 }
420
421 p_t2t->segment = 0;
422
423 for (offset = 0; offset < T2T_READ_DATA_LEN && !failed && !found;) {
424 if (rw_t2t_is_lock_res_byte((uint16_t)(p_t2t->work_offset + offset)) ==
425 true) {
426 /* Skip locks, reserved bytes while searching for TLV */
427 offset++;
428 continue;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800429 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800430 switch (p_t2t->substate) {
431 case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
432 /* Search for the tlv */
433 p_t2t->found_tlv = p_data[offset++];
434 switch (p_t2t->found_tlv) {
435 case TAG_NULL_TLV: /* May be used for padding. SHALL ignore this */
436 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800437
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800438 case TAG_NDEF_TLV:
439 if (tlvtype == TAG_NDEF_TLV) {
440 /* NDEF Detected, now collect NDEF Attributes including NDEF
441 * Length */
442 index = (offset % T2T_BLOCK_SIZE);
443 /* Backup ndef first block */
444 memcpy(p_t2t->ndef_first_block, &p_data[offset - index], index);
445 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
446 } else if (tlvtype == TAG_PROPRIETARY_TLV) {
447 /* Proprietary TLV can exist after NDEF Tlv so we continue
448 * searching */
449 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
450 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
451 (p_t2t->num_lockbytes > 0)) ||
452 ((tlvtype == TAG_MEM_CTRL_TLV) &&
453 (p_t2t->num_mem_tlvs > 0))) {
454 /* Lock / Memory control tlv cannot exist after NDEF TLV
455 * So when NDEF is found, we stop searching for Lock and Memory
456 * control tlv */
457 found = true;
458 } else {
459 /* While searching for Lock / Memory control tlv, if NDEF TLV is
460 * found
461 * first then our search for Lock /Memory control tlv failed and
462 * we stop here */
463 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800464 }
465 break;
466
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800467 case TAG_LOCK_CTRL_TLV:
468 case TAG_MEM_CTRL_TLV:
469 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
470 break;
471
472 case TAG_PROPRIETARY_TLV:
473 if (tlvtype == TAG_PROPRIETARY_TLV) {
474 index = (offset % T2T_BLOCK_SIZE);
475 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
476 } else {
477 /* NDEF/LOCK/MEM TLV can exist after Proprietary Tlv so we
478 * continue searching, skiping proprietary tlv */
479 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
480 }
481 break;
482
483 case TAG_TERMINATOR_TLV: /* Last TLV block in the data area. Must be
484 no NDEF nessage */
485 if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
486 (p_t2t->num_lockbytes > 0)) ||
487 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
488 /* No more Lock/Memory TLV control tlv in the tag, so stop
489 * searching */
490 found = true;
491 } else {
492 /* NDEF/Lock/Memory/Proprietary TLV cannot exist after Terminator
493 * Tlv */
494 failed = true;
495 }
496 break;
497 default:
498 failed = true;
499 }
500 break;
501
502 case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
503 len = p_data[offset];
504 switch (p_t2t->found_tlv) {
505 case TAG_NDEF_TLV:
506 p_t2t->ndef_header_offset = offset + p_t2t->work_offset;
507 if (len == TAG_LONG_NDEF_LEN_FIELD_BYTE0) {
508 /* The next two bytes constitute length bytes */
509 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
510 } else {
511 /* one byte length field */
512 p_t2t->ndef_msg_len = len;
513 p_t2t->bytes_count = p_t2t->ndef_msg_len;
514 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
515 }
516 break;
517
518 case TAG_PROPRIETARY_TLV:
519 if (len == T2T_LONG_NDEF_LEN_FIELD_BYTE0) {
520 /* The next two bytes constitute length bytes */
521 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
522 } else {
523 /* one byte length field */
524 p_t2t->prop_msg_len = len;
525 p_t2t->bytes_count = p_t2t->prop_msg_len;
526 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
527 }
528 break;
529 }
530 offset++;
531 break;
532
533 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
534 switch (p_t2t->found_tlv) {
535 case TAG_LOCK_CTRL_TLV:
536 case TAG_MEM_CTRL_TLV:
537
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800538 len = p_data[offset];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800539 if (len == TAG_DEFAULT_TLV_LEN) {
540 /* Valid Lock control TLV */
541 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
542 p_t2t->bytes_count = TAG_DEFAULT_TLV_LEN;
543 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
544 (p_t2t->num_lockbytes > 0)) ||
545 ((tlvtype == TAG_MEM_CTRL_TLV) &&
546 (p_t2t->num_mem_tlvs > 0))) {
547 /* Stop searching for Lock/ Memory control tlv */
548 found = true;
549 } else {
550 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800551 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800552 break;
553
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800554 case TAG_NDEF_TLV:
555 case TAG_PROPRIETARY_TLV:
556 /* The first length byte */
557 p_t2t->bytes_count = (uint8_t)p_data[offset];
558 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800559 break;
560 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800561 offset++;
562 break;
563
564 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
565 /* Prepare NDEF Message length */
566 p_t2t->bytes_count = (p_t2t->bytes_count << 8) + p_data[offset];
567 if (p_t2t->found_tlv == TAG_NDEF_TLV) {
568 p_t2t->ndef_msg_len = p_t2t->bytes_count;
569 } else if (p_t2t->found_tlv == TAG_PROPRIETARY_TLV) {
570 p_t2t->prop_msg_len = p_t2t->bytes_count;
571 }
572 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
573 offset++;
574 break;
575
576 case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
577 switch (p_t2t->found_tlv) {
578 case TAG_NDEF_TLV:
579 if ((p_t2t->bytes_count == p_t2t->ndef_msg_len) &&
580 (tlvtype == TAG_NDEF_TLV)) {
581 /* The first byte offset after length field */
582 p_t2t->ndef_msg_offset = offset + p_t2t->work_offset;
583 }
584 /* Reduce number of NDEF bytes remaining to pass over NDEF TLV */
585 if (p_t2t->bytes_count > 0) p_t2t->bytes_count--;
586
587 if (tlvtype == TAG_NDEF_TLV) {
588 found = true;
589 p_t2t->ndef_status = T2T_NDEF_DETECTED;
590 } else if (p_t2t->bytes_count == 0) {
591 /* Next byte could be a different TLV */
592 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
593 }
594 break;
595
596 case TAG_LOCK_CTRL_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800597 if (p_t2t->bytes_count > 0) {
598 p_t2t->bytes_count--;
599 } else {
600 LOG(ERROR) << StringPrintf("Underflow p_t2t->bytes_count!");
601 android_errorWriteLog(0x534e4554, "120506143");
602 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800603 if ((tlvtype == TAG_LOCK_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
604 /* Collect Lock TLV */
605 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
606 if (p_t2t->bytes_count == 0) {
607 /* Lock TLV is collected and buffered in tlv_value, now decode
608 * it */
609 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
610 (p_t2t->tlv_value[0] >> 4) & 0x0F;
611 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset *=
612 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
613 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset +=
614 p_t2t->tlv_value[0] & 0x0F;
615 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
616 (uint8_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
617 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits =
618 p_t2t->tlv_value[1];
619 count = p_t2t->tlv_value[1] / 8 +
620 ((p_t2t->tlv_value[1] % 8 != 0) ? 1 : 0);
621
622 /* Extract lockbytes info addressed by this Lock TLV */
623 xx = 0;
Ruchi Kandoi183352b2018-09-21 14:04:22 -0700624 if (count > RW_T2T_MAX_LOCK_BYTES) {
625 count = RW_T2T_MAX_LOCK_BYTES;
626 android_errorWriteLog(0x534e4554, "112161557");
627 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800628 while (xx < count) {
629 p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index =
630 p_t2t->num_lock_tlvs;
631 p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index = xx;
632 p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read = false;
633 xx++;
634 p_t2t->num_lockbytes++;
635 }
636 p_t2t->num_lock_tlvs++;
637 rw_t2t_update_attributes();
638 /* Next byte could be a different TLV */
639 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
640 }
641 } else {
642 /* If not looking for lock/ndef tlv, just skip this Lock TLV */
643 if (p_t2t->bytes_count == 0) {
644 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
645 }
646 }
647 break;
648
649 case TAG_MEM_CTRL_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800650 if (p_t2t->bytes_count > 0) {
651 p_t2t->bytes_count--;
652 } else {
653 LOG(ERROR) << StringPrintf("bytes_count underflow!");
654 android_errorWriteLog(0x534e4554, "120506143");
655 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800656 if ((tlvtype == TAG_MEM_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
657 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
658 if (p_t2t->bytes_count == 0) {
659 if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700660 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800661 "rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated "
662 "for Memory tlv has reached");
663 failed = true;
664 } else {
665 /* Extract memory control tlv */
666 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
667 (p_t2t->tlv_value[0] >> 4) & 0x0F;
668 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
669 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
670 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
671 p_t2t->tlv_value[0] & 0x0F;
672 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
673 p_t2t->tlv_value[1];
674 p_t2t->num_mem_tlvs++;
675 rw_t2t_update_attributes();
676 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
677 }
678 }
679 } else {
680 if (p_t2t->bytes_count == 0) {
681 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
682 }
683 }
684 break;
685
686 case TAG_PROPRIETARY_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800687 if (p_t2t->bytes_count > 0) {
688 p_t2t->bytes_count--;
689 } else {
690 LOG(ERROR) << StringPrintf("bytes_count underflow!");
691 android_errorWriteLog(0x534e4554, "120506143");
692 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800693 if (tlvtype == TAG_PROPRIETARY_TLV) {
694 found = true;
695 p_t2t->prop_msg_len = len;
696 } else {
697 if (p_t2t->bytes_count == 0) {
698 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
699 }
700 }
701 break;
702 }
703 offset++;
704 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800705 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800706 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800707
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800708 p_t2t->work_offset += T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800709
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800710 event = rw_t2t_info_to_event(p_cmd_rsp_info);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800711
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800712 /* If not found and not failed, read next block and search tlv */
713 if (!found && !failed) {
714 if (p_t2t->work_offset >=
715 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR)) {
716 if (((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0)) ||
717 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
718 found = true;
719 } else {
720 failed = true;
721 }
722 } else {
723 if (rw_t2t_read((uint16_t)((p_t2t->work_offset / T2T_BLOCK_LEN) +
724 T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
725 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800726 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800727 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800728
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800729 if (failed || found) {
730 if (tlvtype == TAG_LOCK_CTRL_TLV) {
731 /* Incase no Lock control tlv is present then look for default dynamic
732 * lock bytes */
733 rw_t2t_extract_default_locks_info();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800734
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800735 /* Send command to read the dynamic lock bytes */
736 status = rw_t2t_read_locks();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800737
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800738 if (status != NFC_STATUS_CONTINUE) {
739 /* If unable to read a lock/all locks read, notify upper layer */
740 rw_t2t_update_lock_attributes();
741 rw_t2t_ntf_tlv_detect_complete(status);
742 }
743 } else if (tlvtype == TAG_NDEF_TLV) {
744 rw_t2t_extract_default_locks_info();
745
746 if (failed) {
747 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
748 } else {
749 /* NDEF present,Send command to read the dynamic lock bytes */
750 status = rw_t2t_read_locks();
751 if (status != NFC_STATUS_CONTINUE) {
752 /* If unable to read a lock/all locks read, notify upper layer */
753 rw_t2t_update_lock_attributes();
754 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800755 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800756 }
757 } else {
758 /* Notify Memory/ Proprietary tlv detect result */
759 status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
760 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800761 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800762 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800763}
764
765/*******************************************************************************
766**
767** Function rw_t2t_read_locks
768**
769** Description This function will send command to read next unread locks
770**
771** Returns NFC_STATUS_OK, if all locks are read successfully
772** NFC_STATUS_FAILED, if reading locks failed
773** NFC_STATUS_CONTINUE, if reading locks is in progress
774**
775*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800776tNFC_STATUS rw_t2t_read_locks(void) {
777 uint8_t num_locks = 0;
778 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
779 tNFC_STATUS status = NFC_STATUS_CONTINUE;
780 uint16_t offset;
781 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800782
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800783 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) ||
784 (p_t2t->skip_dyn_locks)) {
785 /* Skip reading dynamic lock bytes if CC is set as Read only or layer above
786 * instructs to skip */
787 while (num_locks < p_t2t->num_lockbytes) {
788 p_t2t->lockbyte[num_locks].lock_byte = 0x00;
789 p_t2t->lockbyte[num_locks].b_lock_read = true;
790 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800791 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800792 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800793
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800794 while (num_locks < p_t2t->num_lockbytes) {
795 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
796 /* Send Read command to read the first un read locks */
797 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
798 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800799
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800800 /* Read 16 bytes where this lock byte is present */
801 block = (uint16_t)(offset / T2T_BLOCK_LEN);
802 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800803
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800804 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
805 /* send READ8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800806 status = rw_t2t_read((uint16_t)block);
807 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800808 /* Reading Locks */
809 status = NFC_STATUS_CONTINUE;
810 } else {
811 status = NFC_STATUS_FAILED;
812 }
813 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800814 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800815 num_locks++;
816 }
817 if (num_locks == p_t2t->num_lockbytes) {
818 /* All locks are read */
819 status = NFC_STATUS_OK;
820 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800821
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800822 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800823}
824
825/*******************************************************************************
826**
827** Function rw_t2t_extract_default_locks_info
828**
829** Description This function will prepare lockbytes information for default
830** locks present in the tag in the absence of lock control tlv.
831** Adding a virtual lock control tlv for these lock bytes for
832** easier manipulation.
833**
834** Returns None
835**
836*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800837void rw_t2t_extract_default_locks_info(void) {
838 uint8_t num_dynamic_lock_bits;
839 uint8_t num_dynamic_lock_bytes;
840 uint8_t xx;
841 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
842 const tT2T_INIT_TAG* p_ret;
843 uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800844
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800845 if ((p_t2t->num_lock_tlvs == 0) &&
846 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
847 /* No Lock control tlv is detected. Indicates lock bytes are present in
848 * default location */
849 /* Add a virtual Lock tlv to map this default lock location */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800850 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
851 if (p_ret != NULL) bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800852
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800853 num_dynamic_lock_bits =
854 ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
855 (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
856 bytes_locked_per_lock_bit;
857 num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
858 num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800859
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800860 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
861 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
862 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
863 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
864 bytes_locked_per_lock_bit;
865 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 -0800866
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800867 /* Based on tag data size the number of locks present in the default
868 * location changes */
869 for (xx = 0; xx < num_dynamic_lock_bytes; xx++) {
870 p_t2t->lockbyte[xx].tlv_index = p_t2t->num_lock_tlvs;
871 p_t2t->lockbyte[xx].byte_index = xx;
872 p_t2t->lockbyte[xx].b_lock_read = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800873 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800874 p_t2t->num_lockbytes = num_dynamic_lock_bytes;
875 p_t2t->num_lock_tlvs = 1;
876 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800877}
878
879/*******************************************************************************
880**
881** Function rw_t2t_read_ndef_last_block
882**
883** Description This function will locate and read the last ndef block.
884** The last ndef block refers to the tag block where last byte
885** of new ndef message will reside. Also this function will
886** locate the offset of Terminator TLV based on the size of
887** new NDEF Message
888**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800889** Returns NCI_STATUS_OK, if able to locate last ndef block & read
890** started. Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800891**
892*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800893tNFC_STATUS rw_t2t_read_ndef_last_block(void) {
894 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
895 uint16_t header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN)
896 ? T2T_LONG_NDEF_LEN_FIELD_LEN
897 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
898 uint16_t num_ndef_bytes;
899 uint16_t total_ndef_bytes;
900 uint16_t last_ndef_byte_offset;
901 uint16_t terminator_tlv_byte_index;
902 tNFC_STATUS status;
903 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800904
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800905 total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
906 num_ndef_bytes = 0;
907 last_ndef_byte_offset = p_t2t->ndef_header_offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800908
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800909 /* Locate NDEF final block based on the size of new NDEF Message */
910 while (num_ndef_bytes < total_ndef_bytes) {
911 if (rw_t2t_is_lock_res_byte((uint16_t)(last_ndef_byte_offset)) == false)
912 num_ndef_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800913
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800914 last_ndef_byte_offset++;
915 }
916 p_t2t->ndef_last_block_num =
917 (uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
918 block = p_t2t->ndef_last_block_num;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800919
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800920 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
921 /* Read NDEF last block before updating */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800922 status = rw_t2t_read(block);
923 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800924 if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
925 /* Locate Terminator TLV Block */
926 total_ndef_bytes++;
927 terminator_tlv_byte_index = last_ndef_byte_offset;
928
929 while (num_ndef_bytes < total_ndef_bytes) {
930 if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
931 false)
932 num_ndef_bytes++;
933
934 terminator_tlv_byte_index++;
935 }
936
937 p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
938 } else {
939 /* No space for Terminator TLV */
940 p_t2t->terminator_byte_index = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800941 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800942 }
943 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800944}
945
946/*******************************************************************************
947**
948** Function rw_t2t_read_terminator_tlv_block
949**
950** Description This function will read the block where terminator tlv will
951** be added later
952**
953** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
954**
955*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800956tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
957 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
958 tNFC_STATUS status;
959 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800960
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800961 /* Send read command to read base block (Block % 4==0) where this block is
962 * also read as part of 16 bytes */
963 block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
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_TERM_TLV_BLOCK;
967 /* Read the block where Terminator TLV may be added later during NDEF Write
968 * operation */
969 status = rw_t2t_read(block);
970 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800971}
972
973/*******************************************************************************
974**
975** Function rw_t2t_read_ndef_next_block
976**
977** Description This function will read the tag block passed as argument
978**
979** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
980**
981*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800982tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block) {
983 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
984 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800985
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800986 /* Send read command to read base block (Block % 4==0) where this block is
987 * also read as part of 16 bytes */
988 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800989
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800990 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
991 /* Read the block */
992 status = rw_t2t_read(block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800993
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800994 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800995}
996
997/*******************************************************************************
998**
999** Function rw_t2t_is_read_before_write_block
1000**
1001** Description This function will check if the block has to be read before
1002** writting to avoid over writting in to lock/reserved bytes
1003** present in the block.
1004** If no bytes in the block can be overwritten it moves in to
1005** next block and check. Finally it finds a block where part of
1006** ndef bytes can exist and check if the whole block can be
1007** updated or only part of block can be modified.
1008**
1009** Returns TRUE, if the block returned should be read before writting
1010** FALSE, if the block need not be read as it was already
1011** read or during NDEF write we may completely overwrite
1012** the block and there is no reserved or locked bytes in
1013** that block
1014**
1015*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001016static bool rw_t2t_is_read_before_write_block(uint16_t block,
1017 uint16_t* p_block_to_read) {
1018 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1019 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1020 uint8_t count;
1021 uint8_t index;
1022 uint16_t tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1023 bool read_before_write = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001024
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001025 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1026 /* First NDEF block is already read */
1027 read_before_write = false;
1028 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
1029 } else if (block == p_t2t->ndef_last_block_num) {
1030 /* Last NDEF block is already read */
1031 read_before_write = false;
1032 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1033 } else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) {
1034 /* Terminator tlv block is already read */
1035 read_before_write = false;
1036 memcpy(p_t2t->ndef_read_block, p_t2t->terminator_tlv_block, T2T_BLOCK_SIZE);
1037 } else {
1038 count = 0;
1039 while (block < tag_size) {
1040 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001041
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001042 while (index < T2T_BLOCK_SIZE) {
1043 /* check if it is a reserved or locked byte */
1044 if (rw_t2t_is_lock_res_byte(
1045 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1046 count++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001047 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001048 index++;
1049 }
1050 if (count == T2T_BLOCK_SIZE) {
1051 /* All the bytes in the block are free to NDEF write */
1052 read_before_write = false;
1053 break;
1054 } else if (count == 0) {
1055 /* The complete block is not free for NDEF write */
1056 index = 0;
1057 block++;
1058 } else {
1059 /* The block has reseved byte (s) or locked byte (s) or both */
1060 read_before_write = true;
1061 break;
1062 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001063 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001064 }
1065 /* Return the block to read next before NDEF write */
1066 *p_block_to_read = block;
1067 return read_before_write;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001068}
1069
1070/*******************************************************************************
1071**
1072** Function rw_t2t_write_ndef_first_block
1073**
1074** Description This function will write the first NDEF block with Length
1075** field reset to zero.
1076** Also after writting NDEF this function may be called to
1077** update new NDEF length
1078**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001079** Returns NCI_STATUS_OK, if write was started.
1080** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001081**
1082*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001083tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len, bool b_update_len) {
1084 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1085 uint8_t new_lengthfield_len;
1086 uint8_t write_block[4];
1087 uint8_t block;
1088 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1089 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1090 tNFC_STATUS status;
1091 uint8_t length_field[3];
1092 uint8_t index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001093
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001094 p_t2t->work_offset = 0;
1095 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1096 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1097 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1098 if (new_lengthfield_len == 3) {
1099 /* New NDEF is Long NDEF */
1100 if (msg_len == 0) {
1101 /* Clear NDEF length field */
1102 length_field[0] = 0x00;
1103 length_field[1] = 0x00;
1104 length_field[2] = 0x00;
1105 } else {
1106 /* Update NDEF length field with new NDEF Msg len */
1107 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1108 length_field[1] = (uint8_t)(msg_len >> 8);
1109 length_field[2] = (uint8_t)(msg_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001110 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001111 } else {
1112 /* New NDEF is Short NDEF */
1113 length_field[0] = (uint8_t)(msg_len);
1114 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001115
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001116 /* updating ndef_first_block with new ndef message */
1117 memcpy(write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001118
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001119 index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1120 block = (uint8_t)(p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001121
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001122 while (p_t2t->work_offset == 0 && block < total_blocks) {
1123 /* update length field */
1124 while (index < T2T_BLOCK_SIZE &&
1125 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1126 if (rw_t2t_is_lock_res_byte(
1127 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1128 write_block[index] = length_field[p_t2t->work_offset];
1129 p_t2t->work_offset++;
1130 }
1131 index++;
1132 if (p_t2t->work_offset == new_lengthfield_len) {
1133 break;
1134 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001135 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001136 /* If more space in this block then add ndef message */
1137 while (index < T2T_BLOCK_SIZE &&
1138 p_t2t->work_offset <
1139 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1140 if (rw_t2t_is_lock_res_byte(
1141 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1142 write_block[index] =
1143 p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1144 p_t2t->work_offset++;
1145 }
1146 index++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001147 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001148 if (p_t2t->work_offset == 0) {
1149 /* If no bytes are written move to next block */
1150 index = 0;
1151 block++;
1152 if (block == p_t2t->ndef_last_block_num) {
1153 memcpy(write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1154 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001155 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001156 }
1157 if (p_t2t->work_offset == 0) {
1158 status = NFC_STATUS_FAILED;
1159 } else {
1160 rw_t2t_update_cb(block, write_block, b_update_len);
1161 /* Update the identified block with newly prepared data */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001162 status = rw_t2t_write(block, write_block);
1163 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001164 p_t2t->b_read_data = false;
1165 }
1166 }
1167 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001168}
1169
1170/*******************************************************************************
1171**
1172** Function rw_t2t_write_ndef_next_block
1173**
1174** Description This function can be called to write an NDEF message block
1175**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001176** Returns NCI_STATUS_OK, if write was started.
1177** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001178**
1179*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001180tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block, uint16_t msg_len,
1181 bool b_update_len) {
1182 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1183 uint8_t new_lengthfield_len;
1184 uint8_t write_block[4];
1185 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1186 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1187 uint16_t initial_offset;
1188 uint8_t length_field[3];
1189 uint8_t index;
1190 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001191
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001192 /* Write NDEF Message */
1193 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1194 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1195 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001196
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001197 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001198
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001199 memcpy(write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001200
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001201 if (p_t2t->work_offset >= new_lengthfield_len) {
1202 /* Length field is updated, write ndef message field */
1203 initial_offset = p_t2t->work_offset;
1204 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1205 while (index < T2T_BLOCK_SIZE &&
1206 p_t2t->work_offset <
1207 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1208 if (rw_t2t_is_lock_res_byte(
1209 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1210 write_block[index] =
1211 p_t2t
1212 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1213 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001214 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001215 index++;
1216 }
1217 if (p_t2t->work_offset == initial_offset) {
1218 index = 0;
1219 block++;
1220 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001221 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001222 } else {
1223 /* Complete writting Length field and then write ndef message */
1224 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1225 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1226 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1227 if (new_lengthfield_len == 3) {
1228 /* New NDEF is Long NDEF */
1229 if (msg_len == 0) {
1230 length_field[0] = 0x00;
1231 length_field[1] = 0x00;
1232 length_field[2] = 0x00;
1233 } else {
1234 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1235 length_field[1] = (uint8_t)(msg_len >> 8);
1236 length_field[2] = (uint8_t)(msg_len);
1237 }
1238 } else {
1239 /* New NDEF is short NDEF */
1240 length_field[0] = (uint8_t)(msg_len);
1241 }
1242 initial_offset = p_t2t->work_offset;
1243 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1244 /* Update length field */
1245 while (index < T2T_BLOCK_SIZE &&
1246 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1247 if (rw_t2t_is_lock_res_byte(
1248 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1249 write_block[index] = length_field[p_t2t->work_offset];
1250 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001251 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001252 index++;
1253 if (p_t2t->work_offset == new_lengthfield_len) {
1254 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001255 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001256 }
1257 /* Update ndef message field */
1258 while (index < T2T_BLOCK_SIZE &&
1259 p_t2t->work_offset <
1260 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1261 if (rw_t2t_is_lock_res_byte(
1262 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1263 write_block[index] =
1264 p_t2t
1265 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1266 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001267 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001268 index++;
1269 }
1270 if (p_t2t->work_offset == initial_offset) {
1271 index = 0;
1272 block++;
1273 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001274 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001275 }
1276 if (p_t2t->work_offset == initial_offset) {
1277 status = NFC_STATUS_FAILED;
1278 } else {
1279 rw_t2t_update_cb(block, write_block, b_update_len);
1280 /* Write the NDEF Block */
1281 status = rw_t2t_write(block, write_block);
1282 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001283
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001284 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001285}
1286
1287/*******************************************************************************
1288**
1289** Function rw_t2t_update_cb
1290**
1291** Description This function can be called to write an NDEF message block
1292**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001293** Returns NCI_STATUS_OK, if write was started.
1294** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001295**
1296*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001297static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
1298 bool b_update_len) {
1299 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1300 uint8_t new_lengthfield_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001301
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001302 /* Write NDEF Message */
1303 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1304 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1305 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001306
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001307 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1308 /* Update ndef first block if the 'block' points to ndef first block */
1309 memcpy(p_t2t->ndef_first_block, p_write_block, T2T_BLOCK_SIZE);
1310 }
1311 if (p_t2t->terminator_byte_index / T2T_BLOCK_SIZE == block) {
1312 /* Update terminator block if the 'block' points to terminator tlv block */
1313 memcpy(p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1314 }
1315 if (b_update_len == false) {
1316 if (block == p_t2t->ndef_last_block_num) {
1317 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1318 p_t2t->work_offset = 0;
1319 /* Update ndef final block if the 'block' points to ndef final block */
1320 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
1321 } else {
1322 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001323 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001324 } else {
1325 if (block == p_t2t->ndef_last_block_num) {
1326 /* Update the backup of Ndef final block TLV block */
1327 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001328 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001329
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001330 if (p_t2t->work_offset >= new_lengthfield_len) {
1331 if (p_t2t->terminator_byte_index != 0) {
1332 /* Add Terminator TLV as part of NDEF Write operation */
1333 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1334 } else {
1335 /* Skip adding Terminator TLV */
1336 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1337 }
1338 } else {
1339 /* Part of NDEF Message Len should be added in the next block */
1340 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001341 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001342 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001343}
1344
1345/*******************************************************************************
1346**
1347** Function rw_t2t_get_ndef_flags
1348**
1349** Description Prepare NDEF Flags
1350**
1351** Returns NDEF Flag value
1352**
1353*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001354static uint8_t rw_t2t_get_ndef_flags(void) {
1355 uint8_t flags = 0;
1356 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1357 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001358
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001359 flags |= RW_NDEF_FL_SUPPORTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001360
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001361 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) ||
1362 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1363 flags |= RW_NDEF_FL_FORMATABLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001364
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001365 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1366 flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001367
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001368 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1369 (p_ret->b_otp)) {
1370 /* Set otp flag */
1371 flags |= RW_NDEF_FL_OTP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001372
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001373 /* Set Read only flag if otp tag already has NDEF Message */
1374 if (p_t2t->ndef_msg_len) flags |= RW_NDEF_FL_READ_ONLY;
1375 }
1376 return flags;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001377}
1378
1379/*******************************************************************************
1380**
1381** Function rw_t2t_get_ndef_max_size
1382**
1383** Description Calculate maximum size of NDEF message that can be written
1384** on to the tag
1385**
1386** Returns Maximum size of NDEF Message
1387**
1388*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001389static uint16_t rw_t2t_get_ndef_max_size(void) {
1390 uint16_t offset;
1391 uint8_t xx;
1392 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1393 uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
1394 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
1395 p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001396
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001397 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1398 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001399
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001400 offset = p_t2t->ndef_msg_offset;
1401 p_t2t->max_ndef_msg_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001402
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001403 if ((tag_size < T2T_STATIC_SIZE) ||
1404 (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
1405 ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
1406 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
1407 /* Tag not formated, assume static tag */
1408 p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
1409 T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001410 return p_t2t->max_ndef_msg_len;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001411 }
1412
1413 /* Starting from NDEF Message offset find the first locked data byte */
1414 while (offset < tag_size) {
1415 if (rw_t2t_is_lock_res_byte((uint16_t)offset) == false) {
1416 if (rw_t2t_is_read_only_byte((uint16_t)offset) == true) break;
1417 p_t2t->max_ndef_msg_len++;
1418 }
1419 offset++;
1420 }
1421 /* NDEF Length field length changes based on NDEF size */
1422 if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
1423 ((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
1424 T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
1425 p_t2t->max_ndef_msg_len -=
1426 (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1427 ? 1
1428 : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1429 }
1430 return p_t2t->max_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001431}
1432
1433/*******************************************************************************
1434**
1435** Function rw_t2t_add_terminator_tlv
1436**
1437** Description This function will add terminator TLV after NDEF Message
1438**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001439** Returns NCI_STATUS_OK, if write was started.
1440** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001441**
1442*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001443tNFC_STATUS rw_t2t_add_terminator_tlv(void) {
1444 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1445 tNFC_STATUS status;
1446 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001447
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001448 /* Add Terminator TLV after NDEF Message */
1449 p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
1450 TAG_TERMINATOR_TLV;
1451 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001452
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001453 block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
1454 status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001455
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001456 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001457}
1458
1459/*******************************************************************************
1460**
1461** Function rw_t2t_handle_ndef_read_rsp
1462**
1463** Description This function handles reading an NDEF message.
1464**
1465** Returns none
1466**
1467*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001468static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data) {
1469 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1470 tRW_READ_DATA evt_data;
1471 uint16_t len;
1472 uint16_t offset;
1473 bool failed = false;
1474 bool done = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001475
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001476 /* On the first read, adjust for any partial block offset */
1477 offset = 0;
1478 len = T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001479
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001480 if (p_t2t->work_offset == 0) {
1481 /* The Ndef Message offset may be present in the read 16 bytes */
1482 offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1483 }
1484
1485 /* Skip all reserved and lock bytes */
1486 while ((offset < len) && (p_t2t->work_offset < p_t2t->ndef_msg_len))
1487
1488 {
1489 if (rw_t2t_is_lock_res_byte(
1490 (uint16_t)(offset + p_t2t->block_read * T2T_BLOCK_LEN)) == false) {
1491 /* Collect the NDEF Message */
1492 p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1493 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001494 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001495 offset++;
1496 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001497
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001498 if (p_t2t->work_offset >= p_t2t->ndef_msg_len) {
1499 done = true;
1500 p_t2t->ndef_status = T2T_NDEF_READ;
1501 } else {
1502 /* Read next 4 blocks */
1503 if (rw_t2t_read((uint16_t)(p_t2t->block_read + T2T_READ_BLOCKS)) !=
1504 NFC_STATUS_OK)
1505 failed = true;
1506 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001507
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001508 if (failed || done) {
1509 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1510 evt_data.p_data = NULL;
1511 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001512 tRW_DATA rw_data;
1513 rw_data.data = evt_data;
1514 (*rw_cb.p_cback)(RW_T2T_NDEF_READ_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001515 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001516}
1517
1518/*******************************************************************************
1519**
1520** Function rw_t2t_handle_ndef_write_rsp
1521**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001522** Description Handle response received to reading (or part of) NDEF
1523** message.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001524**
1525** Returns none
1526**
1527*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001528static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data) {
1529 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1530 tRW_READ_DATA evt_data;
1531 bool failed = false;
1532 bool done = false;
1533 uint16_t block;
1534 uint8_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001535
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001536 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001537 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1538
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001539 /* Backup the read NDEF first block */
1540 memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1541 /* Read ndef final block */
1542 if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
1543 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001544
1545 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1546
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001547 offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
1548 T2T_BLOCK_SIZE;
1549 /* Backup the read NDEF final block */
1550 memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1551 if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
1552 p_t2t->ndef_last_block_num) {
1553 /* If Terminator TLV will reside on the NDEF Final block */
1554 memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
1555 T2T_BLOCK_LEN);
1556 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1557 failed = true;
1558 } else if (p_t2t->terminator_byte_index != 0) {
1559 /* If there is space for Terminator TLV and if it will reside outside
1560 * NDEF Final block */
1561 if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
1562 } else {
1563 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1564 failed = true;
1565 }
1566 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001567
1568 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1569
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001570 offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
1571 p_t2t->block_read) *
1572 T2T_BLOCK_SIZE);
1573 /* Backup the read Terminator TLV block */
1574 memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001575
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001576 /* Write the first block for new NDEF Message */
1577 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1578 failed = true;
1579 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001580
1581 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1582
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001583 offset = (uint8_t)(p_t2t->ndef_read_block_num - p_t2t->block_read) *
1584 T2T_BLOCK_SIZE;
1585 /* Backup read block */
1586 memcpy(p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001587
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001588 /* Update the block with new NDEF Message */
1589 if (rw_t2t_write_ndef_next_block(p_t2t->ndef_read_block_num, 0x0000,
1590 false) != NFC_STATUS_OK)
1591 failed = true;
1592 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001593
1594 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1595 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001596 if (rw_t2t_is_read_before_write_block(
1597 (uint16_t)(p_t2t->block_written + 1), &block) == true) {
1598 p_t2t->ndef_read_block_num = block;
1599 /* If only part of the block is going to be updated read the block to
1600 retain previous data for
1601 unchanged part of the block */
1602 if (rw_t2t_read_ndef_next_block(block) != NFC_STATUS_OK) failed = true;
1603 } else {
1604 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK) {
1605 /* Directly write the block with new NDEF contents as whole block is
1606 * going to be updated */
1607 if (rw_t2t_write_ndef_next_block(block, p_t2t->new_ndef_msg_len,
1608 true) != NFC_STATUS_OK)
1609 failed = true;
1610 } else {
1611 /* Directly write the block with new NDEF contents as whole block is
1612 * going to be updated */
1613 if (rw_t2t_write_ndef_next_block(block, 0x0000, false) !=
1614 NFC_STATUS_OK)
1615 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001616 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001617 }
1618 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001619
1620 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001621 /* Write the next block for new NDEF Message */
1622 p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1623 if (rw_t2t_is_read_before_write_block((uint16_t)(p_t2t->ndef_write_block),
1624 &block) == true) {
1625 /* If only part of the block is going to be updated read the block to
1626 retain previous data for
1627 part of the block thats not going to be changed */
1628 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1629 if (rw_t2t_read(block) != NFC_STATUS_OK) failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001630
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001631 } else {
1632 /* Update NDEF Message Length in the Tag */
1633 if (rw_t2t_write_ndef_first_block(p_t2t->new_ndef_msg_len, true) !=
1634 NFC_STATUS_OK)
1635 failed = true;
1636 }
1637 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001638
1639 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001640 /* Backup read block */
1641 memcpy(p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001642
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001643 /* Update the block with new NDEF Message */
1644 if (rw_t2t_write_ndef_next_block(p_t2t->block_read,
1645 p_t2t->new_ndef_msg_len,
1646 true) == NFC_STATUS_OK)
1647 p_t2t->ndef_write_block = p_t2t->block_read + 1;
1648 else
1649 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001650
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001651 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001652
1653 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001654 if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
1655 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001656
1657 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001658 done = true;
1659 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001660
1661 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001662 break;
1663 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001664
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001665 if (failed || done) {
1666 evt_data.p_data = NULL;
1667 /* NDEF WRITE Operation is done, inform up the stack */
1668 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1669 if (done) {
1670 if ((p_t2t->ndef_msg_len >= 0x00FF) &&
1671 (p_t2t->new_ndef_msg_len < 0x00FF)) {
1672 p_t2t->ndef_msg_offset -= 2;
1673 } else if ((p_t2t->new_ndef_msg_len >= 0x00FF) &&
1674 (p_t2t->ndef_msg_len < 0x00FF)) {
1675 p_t2t->ndef_msg_offset += 2;
1676 }
1677 p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001678 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001679 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001680 tRW_DATA rw_data;
1681 rw_data.data = evt_data;
1682 (*rw_cb.p_cback)(RW_T2T_NDEF_WRITE_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001683 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001684}
1685
1686/*******************************************************************************
1687**
1688** Function rw_t2t_get_tag_size
1689**
1690** Description This function calculates tag data area size from data read
1691** from block with version number
1692**
1693** Returns TMS of the tag
1694**
1695*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001696static uint8_t rw_t2t_get_tag_size(uint8_t* p_data) {
1697 uint16_t LchunkSize = 0;
1698 uint16_t Num_LChuncks = 0;
1699 uint16_t tms = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001700
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001701 LchunkSize = (uint16_t)p_data[2] << 8 | p_data[3];
1702 Num_LChuncks = (uint16_t)p_data[4] << 8 | p_data[5];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001703
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001704 tms = (uint16_t)(LchunkSize * Num_LChuncks);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001705
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001706 tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001707
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001708 tms /= 0x08;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001709
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001710 return (uint8_t)tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001711}
1712
1713/*******************************************************************************
1714**
1715** Function rw_t2t_handle_config_tag_readonly
1716**
1717** Description This function handles configure type 2 tag as read only
1718**
1719** Returns none
1720**
1721*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001722static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data) {
1723 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1724 tNFC_STATUS status = NFC_STATUS_FAILED;
1725 bool b_notify = false;
1726 uint8_t write_block[T2T_BLOCK_SIZE];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001727 bool b_pending = false;
1728 uint8_t read_lock = 0;
1729 uint8_t num_locks = 0;
1730 uint16_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001731
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001732 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001733 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1734
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001735 /* First soft lock the tag */
1736 rw_t2t_soft_lock_tag();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001737
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001738 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001739
1740 case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1741
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001742 /* Successfully soft locked! Update Tag header for future reference */
1743 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1744 if (!p_t2t->b_hard_lock) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001745 /* Tag configuration complete */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001746 status = NFC_STATUS_OK;
Ruchi Kandoi4a179642017-01-04 10:04:48 -08001747 b_notify = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001748 break;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001749 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001750
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001751 /* Coverity: [FALSE-POSITIVE error] intended fall through */
1752 /* Missing break statement between cases in switch statement */
1753 /* fall through */
1754 case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001755
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001756 num_locks = 0;
1757
1758 while (num_locks < p_t2t->num_lockbytes) {
1759 if (p_t2t->lockbyte[num_locks].lock_status ==
1760 RW_T2T_LOCK_UPDATE_INITIATED) {
1761 /* Update control block as one or more dynamic lock byte (s) are set
1762 */
1763 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1764 }
1765 if (!b_pending &&
1766 p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
1767 /* One or more dynamic lock bits are not set */
1768 b_pending = true;
1769 read_lock = num_locks;
1770 }
1771 num_locks++;
1772 }
1773
1774 if (b_pending) {
1775 /* Read the block where dynamic lock bits are present to avoid writing
1776 * to NDEF bytes in the same block */
1777 offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
1778 p_t2t->lockbyte[read_lock].byte_index;
1779 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1780 status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
1781 } else {
1782 /* Now set Static lock bits as no more dynamic lock bits to set */
1783
1784 /* Copy the internal bytes */
1785 memcpy(write_block,
1786 &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
1787 T2T_INTERNAL_BYTES_LEN);
1788 /* Set all Static lock bits */
1789 write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1790 write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1791 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1792 status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1793 }
1794 break;
1795
1796 case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1797 /* Now set the dynamic lock bits present in the block read now */
1798 status = rw_t2t_set_dynamic_lock_bits(p_data);
1799 break;
1800
1801 case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1802 /* Tag configuration complete */
1803 status = NFC_STATUS_OK;
1804 b_notify = true;
1805 break;
1806 }
1807
1808 if (status != NFC_STATUS_OK || b_notify) {
1809 /* Notify upper layer the result of Configuring Tag as Read only */
Myles Watson1361d522017-09-26 13:39:54 -07001810 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001811 evt.status = status;
1812 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001813 (*rw_cb.p_cback)(RW_T2T_SET_TAG_RO_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001814 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001815}
1816
1817/*******************************************************************************
1818**
1819** Function rw_t2t_handle_format_tag_rsp
1820**
1821** Description This function handles formating a type 2 tag
1822**
1823** Returns none
1824**
1825*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001826static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001827 uint8_t* p;
1828 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1829 tNFC_STATUS status = NFC_STATUS_FAILED;
1830 uint16_t version_no;
1831 const tT2T_INIT_TAG* p_ret;
1832 uint8_t tms;
1833 uint8_t next_block = T2T_FIRST_DATA_BLOCK + 1;
1834 uint16_t addr, locked_area;
1835 bool b_notify = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001836
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001837 p = p_t2t->ndef_final_block;
1838 UINT8_TO_BE_STREAM(p, p_t2t->tlv_value[2]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001839
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001840 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001841 case RW_T2T_SUBSTATE_WAIT_READ_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001842 /* Start format operation */
1843 status = rw_t2t_format_tag();
1844 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001845
1846 case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1847
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001848 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1849 p_t2t->b_read_data = true;
1850 version_no = (uint16_t)p_data[0] << 8 | p_data[1];
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001851 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no);
1852 if (p_ret != NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001853 /* Valid Version Number */
1854 if (p_ret->b_calc_cc) /* Calculate tag size from Version Information */
1855 tms = rw_t2t_get_tag_size(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001856
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001857 else
1858 /* Tag size from Look up table */
1859 tms = p_ret->tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001860
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001861 /* Set CC with the Tag size from look up table or from calculated value
1862 */
1863 status = rw_t2t_set_cc(tms);
1864 }
1865 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001866
1867 case RW_T2T_SUBSTATE_WAIT_SET_CC:
1868
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001869 version_no = (uint16_t)p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1870 if ((version_no == 0) ||
1871 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) ==
1872 NULL) ||
1873 (!p_ret->b_multi_version) || (!p_ret->b_calc_cc)) {
1874 /* Currently Formating a non blank tag or a blank tag with manufacturer
1875 * has only one variant of tag. Set Null NDEF TLV and complete Format
1876 * Operation */
1877 next_block = T2T_FIRST_DATA_BLOCK;
1878 p = p_t2t->ndef_final_block;
1879 } else {
1880 addr = (uint16_t)(
1881 ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1882 ((uint16_t)p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) +
1883 T2T_STATIC_SIZE);
1884 locked_area = ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1885 ((uint16_t)p_t2t->tag_data[6]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001886
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001887 status = rw_t2t_set_lock_tlv(addr, p_t2t->tag_data[7], locked_area);
1888 if (status == NFC_STATUS_REJECTED) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001889 /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format
1890 * Operation */
1891 next_block = T2T_FIRST_DATA_BLOCK;
1892 p = p_t2t->ndef_final_block;
1893 } else
1894 break;
1895 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001896
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001897 /* falls through */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001898 case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
1899
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001900 /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
1901 UINT8_TO_BE_STREAM(p, TAG_NDEF_TLV);
1902 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001903
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001904 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1905 (!p_ret->b_otp)) {
1906 UINT8_TO_BE_STREAM(p, TAG_TERMINATOR_TLV);
1907 } else
1908 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001909
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001910 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
1911 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001912 status = rw_t2t_write(next_block, p_t2t->ndef_final_block);
1913 if (status == NFC_STATUS_OK) p_t2t->b_read_data = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001914 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001915
1916 case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001917 /* Tag Formated successfully */
1918 status = NFC_STATUS_OK;
1919 b_notify = true;
1920 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001921
1922 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001923 break;
1924 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001925
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001926 if (status != NFC_STATUS_OK || b_notify) {
1927 /* Notify upper layer the result of Format op */
Myles Watson1361d522017-09-26 13:39:54 -07001928 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001929 evt.status = status;
1930 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001931 (*rw_cb.p_cback)(RW_T2T_FORMAT_CPLT_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001932 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001933}
1934
1935/*******************************************************************************
1936**
1937** Function rw_t2t_update_attributes
1938**
1939** Description This function will update attribute for the current segment
1940** based on lock and reserved bytes
1941**
1942** Returns None
1943**
1944*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001945static void rw_t2t_update_attributes(void) {
1946 uint8_t count = 0;
1947 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1948 uint16_t lower_offset;
1949 uint16_t upper_offset;
1950 uint16_t offset;
1951 uint8_t num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001952
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001953 /* Prepare attr for the current segment */
1954 memset(p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001955
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001956 /* calculate offset where the current segment starts in the tag */
1957 lower_offset = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
1958 /* calculate offset where the current segment ends in the tag */
1959 upper_offset = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001960
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001961 /* check offset of lock bytes in the tag and update p_t2t->attr
1962 * for every lock byte that is present in the current segment */
1963 count = 0;
1964 while (count < p_t2t->num_lockbytes) {
1965 offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset +
1966 p_t2t->lockbyte[count].byte_index;
1967 if (offset >= lower_offset && offset < upper_offset) {
1968 /* Calculate offset in the current segment as p_t2t->attr is prepared for
1969 * one segment only */
1970 offset %= RW_T2T_SEGMENT_BYTES;
1971 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1972 * lock/reserved byte or not
1973 * So, each array element in p_t2t->attr covers two blocks in the tag as
1974 * T2 block size is 4 and array element size is 8
1975 * Set the corresponding bit in attr to indicate - reserved byte */
1976 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1977 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001978 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001979 count++;
1980 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001981
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001982 /* Search reserved bytes identified by all memory tlvs present in the tag */
1983 count = 0;
1984 while (count < p_t2t->num_mem_tlvs) {
1985 /* check the offset of reserved bytes in the tag and update p_t2t->attr
1986 * for every reserved byte that is present in the current segment */
1987 num_bytes = 0;
1988 while (num_bytes < p_t2t->mem_tlv[count].num_bytes) {
1989 offset = p_t2t->mem_tlv[count].offset + num_bytes;
1990 if (offset >= lower_offset && offset < upper_offset) {
1991 /* Let offset represents offset in the current segment as p_t2t->attr is
1992 * prepared for one segment only */
1993 offset %= RW_T2T_SEGMENT_BYTES;
1994 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1995 * lock/reserved byte or not
1996 * So, each array element in p_t2t->attr covers two blocks in the tag as
1997 * T2 block size is 4 and array element size is 8
1998 * Set the corresponding bit in attr to indicate - reserved byte */
1999 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
2000 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
2001 }
2002 num_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002003 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002004 count++;
2005 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002006}
2007
2008/*******************************************************************************
2009**
2010** Function rw_t2t_get_lock_bits_for_segment
2011**
2012** Description This function returns the offset of lock bits associated for
2013** the specified segment
2014**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002015** Parameters: segment: The segment number to which lock bits are
2016** associated
2017** p_start_byte: The offset of lock byte that contains the
2018** first lock bit for the segment
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002019** p_start_bit: The offset of the lock bit in the lock byte
2020**
2021** p_end_byte: The offset of the last bit associcated to the
2022** segment
2023**
2024** Returns Total number of lock bits assigned to the specified segment
2025**
2026*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002027static uint8_t rw_t2t_get_lock_bits_for_segment(uint8_t segment,
2028 uint8_t* p_start_byte,
2029 uint8_t* p_start_bit,
2030 uint8_t* p_end_byte) {
2031 uint8_t total_bits = 0;
2032 uint16_t byte_count = 0;
2033 uint16_t lower_offset, upper_offset;
2034 uint8_t num_dynamic_locks = 0;
2035 uint8_t bit_count = 0;
2036 uint8_t bytes_locked_per_bit;
2037 uint8_t num_bits;
2038 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2039 bool b_all_bits_are_locks = true;
2040 uint16_t tag_size;
2041 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002042
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002043 tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
2044 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002045
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002046 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2047 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002048
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002049 lower_offset = segment * RW_T2T_SEGMENT_BYTES;
2050 if (segment == 0) {
2051 lower_offset += T2T_STATIC_SIZE;
2052 }
2053 upper_offset = (segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002054
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002055 byte_count = T2T_STATIC_SIZE;
2056 if (tag_size < upper_offset) {
2057 upper_offset = tag_size;
2058 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002059
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002060 *p_start_byte = num_dynamic_locks;
2061 *p_start_bit = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002062
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002063 while ((byte_count <= lower_offset) &&
2064 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2065 bytes_locked_per_bit =
2066 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2067 .bytes_locked_per_bit;
2068 /* Number of bits in the current lock byte */
2069 b_all_bits_are_locks =
2070 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2071 TAG_BITS_PER_BYTE <=
2072 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2073 .num_bits);
2074 num_bits =
2075 b_all_bits_are_locks
2076 ? TAG_BITS_PER_BYTE
2077 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2078 .num_bits %
2079 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002080
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002081 if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset) {
2082 /* Skip this lock byte as it covers different segment */
2083 byte_count += bytes_locked_per_bit * num_bits;
2084 num_dynamic_locks++;
2085 } else {
2086 bit_count = 0;
2087 while (bit_count < num_bits) {
2088 byte_count += bytes_locked_per_bit;
2089 if (byte_count > lower_offset) {
2090 /* First lock bit that is used to lock this segment */
2091 *p_start_byte = num_dynamic_locks;
2092 *p_end_byte = num_dynamic_locks;
2093 *p_start_bit = bit_count;
2094 bit_count++;
2095 total_bits = 1;
2096 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002097 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002098 bit_count++;
2099 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002100 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002101 }
2102 if (num_dynamic_locks == p_t2t->num_lockbytes) {
2103 return 0;
2104 }
2105 while ((byte_count < upper_offset) &&
2106 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2107 bytes_locked_per_bit =
2108 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2109 .bytes_locked_per_bit;
2110 /* Number of bits in the current lock byte */
2111 b_all_bits_are_locks =
2112 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2113 TAG_BITS_PER_BYTE <=
2114 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2115 .num_bits);
2116 num_bits =
2117 b_all_bits_are_locks
2118 ? TAG_BITS_PER_BYTE
2119 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2120 .num_bits %
2121 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002122
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002123 if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count <
2124 upper_offset) {
2125 /* Collect all lock bits that covers the current segment */
2126 byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2127 total_bits += num_bits - bit_count;
2128 bit_count = 0;
2129 *p_end_byte = num_dynamic_locks;
2130 num_dynamic_locks++;
2131 } else {
2132 /* The last lock byte that covers the current segment */
2133 bit_count = 0;
2134 while (bit_count < num_bits) {
2135 /* The last lock bit that is used to lock this segment */
2136 byte_count += bytes_locked_per_bit;
2137 if (byte_count >= upper_offset) {
2138 *p_end_byte = num_dynamic_locks;
2139 total_bits += (bit_count + 1);
2140 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002141 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002142 bit_count++;
2143 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002144 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002145 }
2146 return total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002147}
2148
2149/*******************************************************************************
2150**
2151** Function rw_t2t_update_lock_attributes
2152**
2153** Description This function will check if the tag index passed as
2154** argument is a locked byte and return TRUE or FALSE
2155**
2156** Parameters: index, the index of the byte in the tag
2157**
2158**
2159** Returns TRUE, if the specified index in the tag is a locked or
2160** reserved or otp byte
2161** FALSE, otherwise
2162**
2163*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002164static void rw_t2t_update_lock_attributes(void) {
2165 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2166 uint8_t xx = 0;
2167 uint8_t num_static_lock_bytes = 0;
2168 uint8_t num_dyn_lock_bytes = 0;
2169 uint8_t bits_covered = 0;
2170 uint8_t bytes_covered = 0;
2171 uint8_t block_count = 0;
2172 bool b_all_bits_are_locks = true;
2173 uint8_t bytes_locked_per_lock_bit;
2174 uint8_t start_lock_byte;
2175 uint8_t start_lock_bit;
2176 uint8_t end_lock_byte;
2177 uint8_t num_lock_bits;
2178 uint8_t total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002179
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002180 /* Prepare lock_attr for the current segment */
2181 memset(p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002182
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002183 block_count = 0;
2184 if (p_t2t->segment == 0) {
2185 /* Update lock_attributes based on static lock bytes */
2186 xx = 0;
2187 num_static_lock_bytes = 0;
2188 block_count = 0;
2189 num_lock_bits =
2190 TAG_BITS_PER_BYTE - 1; /* the inner while loop increases xx by 2. need
2191 (-1) to avoid coverity overrun error */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002192
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002193 while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES) {
2194 /* Update lock attribute based on 2 static locks */
2195 while (xx < num_lock_bits) {
2196 p_t2t->lock_attr[block_count] = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002197
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002198 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2199 rw_t2t_mask_bits[xx++]) {
2200 /* If the bit is set then 1 block is locked */
2201 p_t2t->lock_attr[block_count] = 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002202 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002203
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002204 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2205 rw_t2t_mask_bits[xx++]) {
2206 /* If the bit is set then 1 block is locked */
2207 p_t2t->lock_attr[block_count] |= 0xF0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002208 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002209 block_count++;
2210 }
2211 num_static_lock_bytes++;
2212 xx = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002213 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002214 /* UID is always locked, irrespective of the lock value */
2215 p_t2t->lock_attr[0x00] = 0xFF;
2216 }
2217
2218 /* Get lock bits applicable for the current segment */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002219 total_bits = rw_t2t_get_lock_bits_for_segment(
2220 p_t2t->segment, &start_lock_byte, &start_lock_bit, &end_lock_byte);
2221 if (total_bits != 0) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002222 /* update lock_attributes based on current segment using dynamic lock bytes
2223 */
2224 xx = start_lock_bit;
2225 num_dyn_lock_bytes = start_lock_byte;
2226 bits_covered = 0;
2227 bytes_covered = 0;
2228 num_lock_bits = TAG_BITS_PER_BYTE;
2229 p_t2t->lock_attr[block_count] = 0;
2230
2231 while (num_dyn_lock_bytes <= end_lock_byte) {
2232 bytes_locked_per_lock_bit =
2233 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2234 .bytes_locked_per_bit;
2235 /* Find number of bits in the byte are lock bits */
2236 b_all_bits_are_locks =
2237 ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) *
2238 TAG_BITS_PER_BYTE <=
2239 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2240 .num_bits);
2241 num_lock_bits =
2242 b_all_bits_are_locks
2243 ? TAG_BITS_PER_BYTE
2244 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2245 .num_bits %
2246 TAG_BITS_PER_BYTE;
2247
2248 while (xx < num_lock_bits) {
2249 bytes_covered = 0;
2250 while (bytes_covered < bytes_locked_per_lock_bit) {
2251 if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte &
2252 rw_t2t_mask_bits[xx]) {
2253 /* If the bit is set then it is locked */
2254 p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
2255 }
2256 bytes_covered++;
2257 bits_covered++;
2258 if (bits_covered == TAG_BITS_PER_BYTE) {
2259 /* Move to next 8 bytes */
2260 bits_covered = 0;
2261 block_count++;
2262 /* Assume unlocked before updating using locks */
2263 if (block_count < RW_T2T_SEGMENT_SIZE)
2264 p_t2t->lock_attr[block_count] = 0;
2265 }
2266 }
2267 xx++;
2268 }
2269 num_dyn_lock_bytes++;
2270 xx = 0;
2271 }
2272 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002273}
2274
2275/*******************************************************************************
2276**
2277** Function rw_t2t_is_lock_res_byte
2278**
2279** Description This function will check if the tag index passed as
2280** argument is a lock or reserved or otp byte and return
2281** TRUE or FALSE
2282**
2283** Parameters: index, the index of the byte in the tag
2284**
2285**
2286** Returns TRUE, if the specified index in the tag is a locked or
2287** reserved or otp byte
2288** FALSE, otherwise
2289**
2290*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002291static bool rw_t2t_is_lock_res_byte(uint16_t index) {
2292 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002293
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002294 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002295
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002296 if (p_t2t->attr_seg != p_t2t->segment) {
2297 /* Update attributes for the current segment */
2298 rw_t2t_update_attributes();
2299 p_t2t->attr_seg = p_t2t->segment;
2300 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002301
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002302 index = index % RW_T2T_SEGMENT_BYTES;
2303 /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a
2304 * lock/reserved byte or not
2305 * So, each array element in p_t2t->attr covers two blocks in the tag as T2
2306 * block size is 4 and array element size is 8
2307 * Find the block and offset for the index (passed as argument) and Check if
2308 * the offset bit in the
2309 * p_t2t->attr[block/2] is set or not. If the bit is set then it is a
2310 * lock/reserved byte, otherwise not */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002311
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002312 return ((p_t2t->attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0) ? false
2313 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002314}
2315
2316/*******************************************************************************
2317**
2318** Function rw_t2t_is_read_only_byte
2319**
2320** Description This function will check if the tag index passed as
2321** argument is a locked and return
2322** TRUE or FALSE
2323**
2324** Parameters: index, the index of the byte in the tag
2325**
2326**
2327** Returns TRUE, if the specified index in the tag is a locked or
2328** reserved or otp byte
2329** FALSE, otherwise
2330**
2331*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002332static bool rw_t2t_is_read_only_byte(uint16_t index) {
2333 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002334
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002335 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002336
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002337 if (p_t2t->lock_attr_seg != p_t2t->segment) {
2338 /* Update lock attributes for the current segment */
2339 rw_t2t_update_lock_attributes();
2340 p_t2t->lock_attr_seg = p_t2t->segment;
2341 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002342
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002343 index = index % RW_T2T_SEGMENT_BYTES;
2344 /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a
2345 * read only byte or read write byte
2346 * So, each array element in p_t2t->lock_attr covers two blocks of the tag as
2347 * T2 block size is 4 and array element size is 8
2348 * Find the block and offset for the index (passed as argument) and Check if
2349 * the offset bit in
2350 * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a
2351 * read only byte, otherwise read write byte */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002352
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002353 return ((p_t2t->lock_attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0)
2354 ? false
2355 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002356}
2357
2358/*******************************************************************************
2359**
2360** Function rw_t2t_set_dynamic_lock_bits
2361**
2362** Description This function will set dynamic lock bits as part of
2363** configuring tag as read only
2364**
2365** Returns
2366** NFC_STATUS_OK, Command sent to set dynamic lock bits
2367** NFC_STATUS_FAILED: otherwise
2368**
2369*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002370tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data) {
2371 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2372 uint8_t write_block[T2T_BLOCK_SIZE];
2373 uint16_t offset;
2374 uint16_t next_offset;
2375 uint8_t num_bits;
2376 uint8_t next_num_bits;
2377 tNFC_STATUS status = NFC_STATUS_FAILED;
2378 uint8_t num_locks;
2379 uint8_t lock_count;
2380 bool b_all_bits_are_locks = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002381
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002382 num_locks = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002383
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002384 memcpy(write_block, p_data, T2T_BLOCK_SIZE);
2385 while (num_locks < p_t2t->num_lockbytes) {
2386 if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
2387 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
2388 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002389
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002390 /* Check if all bits are lock bits in the byte */
2391 b_all_bits_are_locks =
2392 ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <=
2393 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2394 num_bits =
2395 b_all_bits_are_locks
2396 ? TAG_BITS_PER_BYTE
2397 : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits %
2398 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002399
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002400 write_block[(uint8_t)(offset % T2T_BLOCK_SIZE)] |=
2401 tags_pow(2, num_bits) - 1;
2402 lock_count = num_locks + 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002403
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002404 /* Set all the lock bits in the block using a sing block write command */
2405 while (lock_count < p_t2t->num_lockbytes) {
2406 next_offset =
2407 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset +
2408 p_t2t->lockbyte[lock_count].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002409
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002410 /* Check if all bits are lock bits in the byte */
2411 b_all_bits_are_locks =
2412 ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <=
2413 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2414 next_num_bits =
2415 b_all_bits_are_locks
2416 ? TAG_BITS_PER_BYTE
2417 : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index]
2418 .num_bits %
2419 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002420
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002421 if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE) {
2422 write_block[(uint8_t)(next_offset % T2T_BLOCK_SIZE)] |=
2423 tags_pow(2, next_num_bits) - 1;
2424 } else
2425 break;
2426 lock_count++;
2427 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002428
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002429 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2430 /* send WRITE command to set dynamic lock bits */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002431 status = rw_t2t_write((uint16_t)(offset / T2T_BLOCK_SIZE), write_block);
2432 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002433 while (lock_count > num_locks) {
2434 /* Set update initiated flag to indicate a write command is sent to
2435 * set dynamic lock bits of the block */
2436 p_t2t->lockbyte[lock_count - 1].lock_status =
2437 RW_T2T_LOCK_UPDATE_INITIATED;
2438 lock_count--;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002439 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002440 } else
2441 status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002442
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002443 break;
2444 }
2445 num_locks++;
2446 }
2447
2448 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002449}
2450
2451/*******************************************************************************
2452**
2453** Function rw_t2t_set_lock_tlv
2454**
2455** Description This function will set lock control tlv on the blank
2456** activated type 2 tag based on values read from version block
2457**
2458** Parameters: TAG data memory size
2459**
2460** Returns
2461** NFC_STATUS_OK, Command sent to set Lock TLV
2462** NFC_STATUS_FAILED: otherwise
2463**
2464*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002465tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
2466 uint16_t locked_area_size) {
2467 tNFC_STATUS status = NFC_STATUS_FAILED;
2468 int8_t PageAddr = 0;
2469 int8_t BytePerPage = 0;
2470 int8_t ByteOffset = 0;
2471 uint8_t a;
2472 uint8_t data_block[T2T_BLOCK_SIZE];
2473 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2474 uint8_t* p;
2475 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002476
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002477 for (xx = 15; xx > 0; xx--) {
2478 a = (uint8_t)(addr / xx);
2479 a += (addr % xx) ? 1 : 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002480
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002481 BytePerPage = (int8_t)tags_log2(a);
2482 ByteOffset = (int8_t)(addr - xx * tags_pow(2, BytePerPage));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002483
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002484 if (ByteOffset < 16) {
2485 PageAddr = xx;
2486 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002487 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002488 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002489
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002490 if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16)) {
2491 memset(data_block, 0, T2T_BLOCK_SIZE);
2492 p = data_block;
2493 UINT8_TO_BE_STREAM(p, T2T_TLV_TYPE_LOCK_CTRL);
2494 UINT8_TO_BE_STREAM(p, T2T_TLEN_LOCK_CTRL_TLV);
2495 UINT8_TO_BE_STREAM(p, (PageAddr << 4 | ByteOffset));
2496 UINT8_TO_BE_STREAM(p, num_dyn_lock_bits);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002497
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002498 p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2499 p_t2t->tlv_value[1] = num_dyn_lock_bits;
2500 p_t2t->tlv_value[2] =
2501 (uint8_t)(BytePerPage << 4 | tags_log2(locked_area_size));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002502
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002503 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002504
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002505 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002506 status = rw_t2t_write(T2T_FIRST_DATA_BLOCK, data_block);
2507 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002508 p_t2t->b_read_data = false;
2509 } else
2510 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2511 } else
2512 status = NFC_STATUS_REJECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002513
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002514 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002515}
2516
2517/*******************************************************************************
2518**
2519** Function rw_t2t_set_cc
2520**
2521** Description This function will set Capability Container on the activated
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002522** type 2 tag with default values of CC0, CC1, CC4 and
2523** specified CC3 value
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002524**
2525** Parameters: CC3 value of the tag
2526**
2527** Returns
2528** NFC_STATUS_OK, Command sent to set CC
2529** NFC_STATUS_FAILED: otherwise
2530**
2531*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002532tNFC_STATUS rw_t2t_set_cc(uint8_t tms) {
2533 uint8_t cc_block[T2T_BLOCK_SIZE];
2534 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2535 tNFC_STATUS status = NFC_STATUS_FAILED;
2536 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002537
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002538 memset(cc_block, 0, T2T_BLOCK_SIZE);
2539 memset(p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2540 p = cc_block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002541
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002542 /* Prepare Capability Container */
2543 UINT8_TO_BE_STREAM(p, T2T_CC0_NMN);
2544 UINT8_TO_BE_STREAM(p, T2T_CC1_VNO);
2545 UINT8_TO_BE_STREAM(p, tms);
2546 UINT8_TO_BE_STREAM(p, T2T_CC3_RWA_RW);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002547
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002548 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002549
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002550 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002551 status = rw_t2t_write(T2T_CC_BLOCK, cc_block);
2552 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002553 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2554 p_t2t->b_read_hdr = false;
2555 } else
2556 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002557
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002558 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002559}
2560
2561/*******************************************************************************
2562**
2563** Function rw_t2t_format_tag
2564**
2565** Description This function will format tag based on Manufacturer ID
2566**
2567** Returns
2568** NFC_STATUS_OK, Command sent to format Tag
2569** NFC_STATUS_FAILED: otherwise
2570**
2571*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002572tNFC_STATUS rw_t2t_format_tag(void) {
2573 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2574 const tT2T_INIT_TAG* p_ret;
2575 uint8_t tms;
2576 tNFC_STATUS status = NFC_STATUS_FAILED;
2577 bool b_blank_tag = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002578
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002579 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
2580 if (p_ret == NULL) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002581 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002582 "rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the "
2583 "tag!",
2584 p_t2t->tag_hdr[0]);
2585 return (NFC_STATUS_FAILED);
2586 }
2587
2588 if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0) {
2589 /* If OTP tag has valid NDEF Message, cannot format the tag */
2590 if ((p_t2t->ndef_msg_len > 0) && (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002591 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002592 "rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2593 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002594 }
2595
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002596 if (((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) &&
2597 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) ||
2598 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) &&
2599 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
2600 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
2601 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002602 LOG(WARNING) << StringPrintf(
2603 "rw_t2t_format_tag - Tag not blank to Format!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002604 return (NFC_STATUS_FAILED);
2605 } else {
2606 tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2607 b_blank_tag = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002608 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002609 } else
2610 tms = p_ret->tms;
2611
2612 memset(p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2613
2614 if (!b_blank_tag || !p_ret->b_multi_version) {
2615 status = rw_t2t_set_cc(tms);
2616 } else if (p_ret->version_block != 0) {
2617 /* If Version number is not read, READ it now */
2618 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2619
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002620 status = rw_t2t_read(p_ret->version_block);
2621 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002622 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002623 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002624 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2625 } else {
2626 /* UID block is the version block */
2627 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2628 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2629 rw_t2t_handle_format_tag_rsp(p_t2t->tag_hdr);
2630 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002631
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002632 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002633}
2634
2635/*******************************************************************************
2636**
2637** Function rw_t2t_soft_lock_tag
2638**
2639** Description This function will soft lock the tag after validating CC.
2640**
2641** Returns
2642** NFC_STATUS_OK, Command sent to soft lock the tag
2643** NFC_STATUS_FAILED: otherwise
2644**
2645*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002646tNFC_STATUS rw_t2t_soft_lock_tag(void) {
2647 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2648 tNFC_STATUS status = NFC_STATUS_FAILED;
2649 uint8_t write_block[T2T_BLOCK_SIZE];
2650 uint8_t num_locks;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002651
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002652 /* If CC block is read and cc3 is soft locked, reject the command */
2653 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002654 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002655 "rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: "
2656 "%u",
2657 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2658 return (NFC_STATUS_FAILED);
2659 }
2660
2661 if (p_t2t->b_hard_lock) {
2662 /* Should have performed NDEF Detection on dynamic memory structure tag,
2663 * before permanently converting to Read only
2664 * Even when no lock control tlv is present, default lock bytes should be
2665 * present */
2666
2667 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) &&
2668 (p_t2t->num_lockbytes == 0)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002669 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002670 "rw_t2t_soft_lock_tag: Error: Lock TLV not detected! Cannot hard "
2671 "lock the tag");
2672 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002673 }
2674
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002675 /* On dynamic memory structure tag, reset all lock bytes status to 'Not
2676 * Updated' if not in Updated status */
2677 num_locks = 0;
2678 while (num_locks < p_t2t->num_lockbytes) {
2679 if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2680 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2681 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002682 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002683 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002684
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002685 memcpy(write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2686 write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002687
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002688 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2689 /* First Soft lock the tag */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002690 status = rw_t2t_write(T2T_CC_BLOCK, write_block);
2691 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002692 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
2693 p_t2t->b_read_hdr = false;
2694 } else {
2695 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2696 }
2697 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002698}
2699
2700/*****************************************************************************
2701**
2702** Function RW_T2tFormatNDef
2703**
2704** Description
2705** Format Tag content
2706**
2707** Returns
2708** NFC_STATUS_OK, Command sent to format Tag
2709** NFC_STATUS_FAILED: otherwise
2710**
2711*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002712tNFC_STATUS RW_T2tFormatNDef(void) {
2713 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2714 tNFC_STATUS status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002715
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002716 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002717 LOG(WARNING) << StringPrintf(
2718 "RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u",
2719 p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002720 return (NFC_STATUS_FAILED);
2721 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002722
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002723 if (!p_t2t->b_read_hdr) {
2724 /* If UID is not read, READ it now */
2725 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002726
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002727 status = rw_t2t_read(0);
2728 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002729 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002730 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002731 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2732 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002733 status = rw_t2t_format_tag();
2734 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002735 }
2736 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002737}
2738
2739/*******************************************************************************
2740**
2741** Function RW_T2tLocateTlv
2742**
2743** Description This function is used to perform TLV detection on a Type 2
2744** tag, and retrieve the tag's TLV attribute information.
2745**
2746** Before using this API, the application must call
2747** RW_SelectTagType to indicate that a Type 2 tag has been
2748** activated.
2749**
2750** Parameters: tlv_type : TLV to detect
2751**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002752** Returns NCI_STATUS_OK, if detection was started. Otherwise, error
2753** status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002754**
2755*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002756tNFC_STATUS RW_T2tLocateTlv(uint8_t tlv_type) {
2757 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2758 tNFC_STATUS status;
2759 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002760
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002761 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002762 LOG(ERROR) << StringPrintf(
2763 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002764 return (NFC_STATUS_BUSY);
2765 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002766
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002767 if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) &&
2768 (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002769 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2770 "RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002771 return (NFC_STATUS_FAILED);
2772 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002773
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002774 if ((tlv_type == TAG_LOCK_CTRL_TLV) && (p_t2t->b_read_hdr) &&
2775 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)) {
2776 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002777 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002778 "RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x",
2779 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2780 return (NFC_STATUS_FAILED);
2781 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002782
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002783 if ((tlv_type == TAG_NDEF_TLV) && (p_t2t->b_read_hdr) &&
2784 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) {
2785 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002786 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002787 "RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: "
2788 "0x%02x, CC[3]: 0x%02x",
2789 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
2790 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2791 return (NFC_STATUS_FAILED);
2792 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002793
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002794 p_t2t->work_offset = 0;
2795 p_t2t->tlv_detect = tlv_type;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002796
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002797 /* Reset control block variables based on type of tlv to detect */
2798 if (tlv_type == TAG_LOCK_CTRL_TLV) {
2799 p_t2t->num_lockbytes = 0;
2800 p_t2t->num_lock_tlvs = 0;
2801 } else if (tlv_type == TAG_MEM_CTRL_TLV) {
2802 p_t2t->num_mem_tlvs = 0;
2803 } else if (tlv_type == TAG_NDEF_TLV) {
2804 p_t2t->ndef_msg_offset = 0;
2805 p_t2t->num_lockbytes = 0;
2806 p_t2t->num_lock_tlvs = 0;
2807 p_t2t->num_mem_tlvs = 0;
2808 p_t2t->ndef_msg_len = 0;
2809 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
2810 } else {
2811 p_t2t->prop_msg_len = 0;
2812 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002813
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002814 if (!p_t2t->b_read_hdr) {
2815 /* First read CC block */
2816 block = 0;
2817 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2818 } else {
2819 /* Read first data block */
2820 block = T2T_FIRST_DATA_BLOCK;
2821 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2822 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002823
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002824 /* Start reading tag, looking for the specified TLV */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002825 status = rw_t2t_read((uint16_t)block);
2826 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002827 p_t2t->state = RW_T2T_STATE_DETECT_TLV;
2828 } else {
2829 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2830 }
2831 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002832}
2833
2834/*******************************************************************************
2835**
2836** Function RW_T2tDetectNDef
2837**
2838** Description This function is used to perform NDEF detection on a Type 2
2839** tag, and retrieve the tag's NDEF attribute information.
2840**
2841** Before using this API, the application must call
2842** RW_SelectTagType to indicate that a Type 2 tag has been
2843** activated.
2844**
2845** Parameters: none
2846**
2847** Returns NCI_STATUS_OK,if detect op started.Otherwise,error status.
2848**
2849*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002850tNFC_STATUS RW_T2tDetectNDef(bool skip_dyn_locks) {
2851 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Evan Chuc95c79c2013-04-12 17:38:09 -04002852
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002853 p_t2t->skip_dyn_locks = skip_dyn_locks;
Evan Chuc95c79c2013-04-12 17:38:09 -04002854
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002855 return RW_T2tLocateTlv(TAG_NDEF_TLV);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002856}
2857
2858/*******************************************************************************
2859**
2860** Function RW_T2tReadNDef
2861**
2862** Description Retrieve NDEF contents from a Type2 tag.
2863**
2864** The RW_T2T_NDEF_READ_EVT event is used to notify the
2865** application after reading the NDEF message.
2866**
2867** Before using this API, the RW_T2tDetectNDef function must
2868** be called to verify that the tag contains NDEF data, and to
2869** retrieve the NDEF attributes.
2870**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002871** Internally, this command will be separated into multiple
2872** Tag2 Read commands (if necessary) - depending on the NDEF
2873** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002874**
2875** Parameters: p_buffer: The buffer into which to read the NDEF message
2876** buf_len: The length of the buffer
2877**
2878** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
2879**
2880*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002881tNFC_STATUS RW_T2tReadNDef(uint8_t* p_buffer, uint16_t buf_len) {
2882 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2883 tNFC_STATUS status = NFC_STATUS_OK;
2884 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002885
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002886 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002887 LOG(ERROR) << StringPrintf(
2888 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002889 return (NFC_STATUS_FAILED);
2890 }
2891
2892 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002893 LOG(ERROR) << StringPrintf(
2894 "RW_T2tReadNDef - Error: NDEF detection not performed yet");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002895 return (NFC_STATUS_FAILED);
2896 }
2897
2898 if (buf_len < p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002899 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002900 "RW_T2tReadNDef - buffer size: %u less than NDEF msg sise: %u",
2901 buf_len, p_t2t->ndef_msg_len);
2902 return (NFC_STATUS_FAILED);
2903 }
2904
2905 if (!p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002906 LOG(WARNING) << StringPrintf(
2907 "RW_T2tReadNDef - NDEF Message length is zero");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002908 return (NFC_STATUS_NOT_INITIALIZED);
2909 }
2910
2911 p_t2t->p_ndef_buffer = p_buffer;
2912 p_t2t->work_offset = 0;
2913
2914 block = (uint16_t)(p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
2915 block -= block % T2T_READ_BLOCKS;
2916
2917 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2918
2919 if ((block == T2T_FIRST_DATA_BLOCK) && (p_t2t->b_read_data)) {
2920 p_t2t->state = RW_T2T_STATE_READ_NDEF;
2921 p_t2t->block_read = T2T_FIRST_DATA_BLOCK;
2922 rw_t2t_handle_ndef_read_rsp(p_t2t->tag_data);
2923 } else {
2924 /* Start reading NDEF Message */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002925 status = rw_t2t_read(block);
2926 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002927 p_t2t->state = RW_T2T_STATE_READ_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002928 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002929 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002930
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002931 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002932}
2933
2934/*******************************************************************************
2935**
2936** Function RW_T2tWriteNDef
2937**
2938** Description Write NDEF contents to a Type2 tag.
2939**
2940** Before using this API, the RW_T2tDetectNDef
2941** function must be called to verify that the tag contains
2942** NDEF data, and to retrieve the NDEF attributes.
2943**
2944** The RW_T2T_NDEF_WRITE_EVT callback event will be used to
2945** notify the application of the response.
2946**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002947** Internally, this command will be separated into multiple
2948** Tag2 Write commands (if necessary) - depending on the NDEF
2949** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002950**
2951** Parameters: msg_len: The length of the buffer
2952** p_msg: The NDEF message to write
2953**
2954** Returns NCI_STATUS_OK,if write was started. Otherwise, error status
2955**
2956*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002957tNFC_STATUS RW_T2tWriteNDef(uint16_t msg_len, uint8_t* p_msg) {
2958 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2959 uint16_t block;
2960 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002961
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002962 tNFC_STATUS status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002963
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002964 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002965 LOG(ERROR) << StringPrintf(
2966 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002967 return (NFC_STATUS_FAILED);
2968 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002969
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002970 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002971 LOG(ERROR) << StringPrintf(
2972 "RW_T2tWriteNDef - Error: NDEF detection not performed!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002973 return (NFC_STATUS_FAILED);
2974 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002975
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002976 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002977 LOG(ERROR) << StringPrintf(
2978 "RW_T2tWriteNDef - Write access not granted - CC3: %u",
2979 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002980 return (NFC_STATUS_REFUSED);
2981 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002982
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002983 /* Check if there is enough memory on the tag */
2984 if (msg_len > p_t2t->max_ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002985 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002986 "RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes",
2987 p_t2t->max_ndef_msg_len);
2988 return (NFC_STATUS_FAILED);
2989 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002990
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002991 /* If OTP tag and tag has valid NDEF Message, stop writting new NDEF Message
2992 * as it may corrupt the tag */
2993 if ((p_t2t->ndef_msg_len > 0) &&
2994 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
2995 (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002996 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002997 "RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
2998 return (NFC_STATUS_FAILED);
2999 }
3000 p_t2t->p_new_ndef_buffer = p_msg;
3001 p_t2t->new_ndef_msg_len = msg_len;
3002 p_t2t->work_offset = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003003
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003004 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
3005 /* Read first NDEF Block before updating NDEF */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003006
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003007 block = (uint16_t)(p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003008
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003009 if ((block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) &&
3010 (p_t2t->b_read_data)) {
3011 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
3012 p_t2t->block_read = block;
3013 rw_t2t_handle_ndef_write_rsp(
3014 &p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
3015 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003016 status = rw_t2t_read(block);
3017 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003018 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003019 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003020 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3021 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003022
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003023 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003024}
3025
3026/*******************************************************************************
3027**
3028** Function RW_T2tSetTagReadOnly
3029**
3030** Description This function can be called to set T2 tag as read only.
3031**
3032** Parameters: b_hard_lock: To indicate hard lock the tag or not
3033**
3034** Returns NCI_STATUS_OK, if setting tag as read only was started.
3035** Otherwise, error status.
3036**
3037*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003038tNFC_STATUS RW_T2tSetTagReadOnly(bool b_hard_lock) {
3039 tNFC_STATUS status = NFC_STATUS_FAILED;
3040 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003041
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003042 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003043 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003044 "RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - "
3045 "State: %u",
3046 p_t2t->state);
3047 return (NFC_STATUS_FAILED);
3048 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003049
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003050 p_t2t->b_hard_lock = b_hard_lock;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003051
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003052 if (!p_t2t->b_read_hdr) {
3053 /* Read CC block before configuring tag as Read only */
3054 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003055 status = rw_t2t_read((uint16_t)0);
3056 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003057 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
3058 } else
3059 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3060 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003061 status = rw_t2t_soft_lock_tag();
3062 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003063 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003064
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003065 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003066}
3067
Ruchi Kandoi303fec12016-12-14 13:22:38 -08003068#endif /* (RW_NDEF_INCLUDED == TRUE) */