blob: 03d205e8da765824fbf476e5ba1cb1a6d9c81138 [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:
597 p_t2t->bytes_count--;
598 if ((tlvtype == TAG_LOCK_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
599 /* Collect Lock TLV */
600 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
601 if (p_t2t->bytes_count == 0) {
602 /* Lock TLV is collected and buffered in tlv_value, now decode
603 * it */
604 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
605 (p_t2t->tlv_value[0] >> 4) & 0x0F;
606 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset *=
607 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
608 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset +=
609 p_t2t->tlv_value[0] & 0x0F;
610 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
611 (uint8_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
612 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits =
613 p_t2t->tlv_value[1];
614 count = p_t2t->tlv_value[1] / 8 +
615 ((p_t2t->tlv_value[1] % 8 != 0) ? 1 : 0);
616
617 /* Extract lockbytes info addressed by this Lock TLV */
618 xx = 0;
Ruchi Kandoi183352b2018-09-21 14:04:22 -0700619 if (count > RW_T2T_MAX_LOCK_BYTES) {
620 count = RW_T2T_MAX_LOCK_BYTES;
621 android_errorWriteLog(0x534e4554, "112161557");
622 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800623 while (xx < count) {
624 p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index =
625 p_t2t->num_lock_tlvs;
626 p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index = xx;
627 p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read = false;
628 xx++;
629 p_t2t->num_lockbytes++;
630 }
631 p_t2t->num_lock_tlvs++;
632 rw_t2t_update_attributes();
633 /* Next byte could be a different TLV */
634 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
635 }
636 } else {
637 /* If not looking for lock/ndef tlv, just skip this Lock TLV */
638 if (p_t2t->bytes_count == 0) {
639 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
640 }
641 }
642 break;
643
644 case TAG_MEM_CTRL_TLV:
645 p_t2t->bytes_count--;
646 if ((tlvtype == TAG_MEM_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
647 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
648 if (p_t2t->bytes_count == 0) {
649 if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700650 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800651 "rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated "
652 "for Memory tlv has reached");
653 failed = true;
654 } else {
655 /* Extract memory control tlv */
656 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
657 (p_t2t->tlv_value[0] >> 4) & 0x0F;
658 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
659 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
660 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
661 p_t2t->tlv_value[0] & 0x0F;
662 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
663 p_t2t->tlv_value[1];
664 p_t2t->num_mem_tlvs++;
665 rw_t2t_update_attributes();
666 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
667 }
668 }
669 } else {
670 if (p_t2t->bytes_count == 0) {
671 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
672 }
673 }
674 break;
675
676 case TAG_PROPRIETARY_TLV:
677 p_t2t->bytes_count--;
678 if (tlvtype == TAG_PROPRIETARY_TLV) {
679 found = true;
680 p_t2t->prop_msg_len = len;
681 } else {
682 if (p_t2t->bytes_count == 0) {
683 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
684 }
685 }
686 break;
687 }
688 offset++;
689 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800690 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800691 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800692
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800693 p_t2t->work_offset += T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800694
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800695 event = rw_t2t_info_to_event(p_cmd_rsp_info);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800696
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800697 /* If not found and not failed, read next block and search tlv */
698 if (!found && !failed) {
699 if (p_t2t->work_offset >=
700 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR)) {
701 if (((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0)) ||
702 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
703 found = true;
704 } else {
705 failed = true;
706 }
707 } else {
708 if (rw_t2t_read((uint16_t)((p_t2t->work_offset / T2T_BLOCK_LEN) +
709 T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
710 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800711 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800712 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800713
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800714 if (failed || found) {
715 if (tlvtype == TAG_LOCK_CTRL_TLV) {
716 /* Incase no Lock control tlv is present then look for default dynamic
717 * lock bytes */
718 rw_t2t_extract_default_locks_info();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800719
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800720 /* Send command to read the dynamic lock bytes */
721 status = rw_t2t_read_locks();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800722
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800723 if (status != NFC_STATUS_CONTINUE) {
724 /* If unable to read a lock/all locks read, notify upper layer */
725 rw_t2t_update_lock_attributes();
726 rw_t2t_ntf_tlv_detect_complete(status);
727 }
728 } else if (tlvtype == TAG_NDEF_TLV) {
729 rw_t2t_extract_default_locks_info();
730
731 if (failed) {
732 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
733 } else {
734 /* NDEF present,Send command to read the dynamic lock bytes */
735 status = rw_t2t_read_locks();
736 if (status != NFC_STATUS_CONTINUE) {
737 /* If unable to read a lock/all locks read, notify upper layer */
738 rw_t2t_update_lock_attributes();
739 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800740 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800741 }
742 } else {
743 /* Notify Memory/ Proprietary tlv detect result */
744 status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
745 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800746 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800747 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800748}
749
750/*******************************************************************************
751**
752** Function rw_t2t_read_locks
753**
754** Description This function will send command to read next unread locks
755**
756** Returns NFC_STATUS_OK, if all locks are read successfully
757** NFC_STATUS_FAILED, if reading locks failed
758** NFC_STATUS_CONTINUE, if reading locks is in progress
759**
760*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800761tNFC_STATUS rw_t2t_read_locks(void) {
762 uint8_t num_locks = 0;
763 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
764 tNFC_STATUS status = NFC_STATUS_CONTINUE;
765 uint16_t offset;
766 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800767
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800768 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) ||
769 (p_t2t->skip_dyn_locks)) {
770 /* Skip reading dynamic lock bytes if CC is set as Read only or layer above
771 * instructs to skip */
772 while (num_locks < p_t2t->num_lockbytes) {
773 p_t2t->lockbyte[num_locks].lock_byte = 0x00;
774 p_t2t->lockbyte[num_locks].b_lock_read = true;
775 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800776 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800777 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800778
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800779 while (num_locks < p_t2t->num_lockbytes) {
780 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
781 /* Send Read command to read the first un read locks */
782 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
783 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800784
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800785 /* Read 16 bytes where this lock byte is present */
786 block = (uint16_t)(offset / T2T_BLOCK_LEN);
787 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800788
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800789 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
790 /* send READ8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800791 status = rw_t2t_read((uint16_t)block);
792 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800793 /* Reading Locks */
794 status = NFC_STATUS_CONTINUE;
795 } else {
796 status = NFC_STATUS_FAILED;
797 }
798 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800799 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800800 num_locks++;
801 }
802 if (num_locks == p_t2t->num_lockbytes) {
803 /* All locks are read */
804 status = NFC_STATUS_OK;
805 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800806
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800807 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800808}
809
810/*******************************************************************************
811**
812** Function rw_t2t_extract_default_locks_info
813**
814** Description This function will prepare lockbytes information for default
815** locks present in the tag in the absence of lock control tlv.
816** Adding a virtual lock control tlv for these lock bytes for
817** easier manipulation.
818**
819** Returns None
820**
821*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800822void rw_t2t_extract_default_locks_info(void) {
823 uint8_t num_dynamic_lock_bits;
824 uint8_t num_dynamic_lock_bytes;
825 uint8_t xx;
826 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
827 const tT2T_INIT_TAG* p_ret;
828 uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800829
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800830 if ((p_t2t->num_lock_tlvs == 0) &&
831 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
832 /* No Lock control tlv is detected. Indicates lock bytes are present in
833 * default location */
834 /* Add a virtual Lock tlv to map this default lock location */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800835 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
836 if (p_ret != NULL) bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800837
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800838 num_dynamic_lock_bits =
839 ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
840 (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
841 bytes_locked_per_lock_bit;
842 num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
843 num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800844
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800845 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
846 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
847 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
848 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
849 bytes_locked_per_lock_bit;
850 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 -0800851
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800852 /* Based on tag data size the number of locks present in the default
853 * location changes */
854 for (xx = 0; xx < num_dynamic_lock_bytes; xx++) {
855 p_t2t->lockbyte[xx].tlv_index = p_t2t->num_lock_tlvs;
856 p_t2t->lockbyte[xx].byte_index = xx;
857 p_t2t->lockbyte[xx].b_lock_read = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800858 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800859 p_t2t->num_lockbytes = num_dynamic_lock_bytes;
860 p_t2t->num_lock_tlvs = 1;
861 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800862}
863
864/*******************************************************************************
865**
866** Function rw_t2t_read_ndef_last_block
867**
868** Description This function will locate and read the last ndef block.
869** The last ndef block refers to the tag block where last byte
870** of new ndef message will reside. Also this function will
871** locate the offset of Terminator TLV based on the size of
872** new NDEF Message
873**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800874** Returns NCI_STATUS_OK, if able to locate last ndef block & read
875** started. Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800876**
877*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800878tNFC_STATUS rw_t2t_read_ndef_last_block(void) {
879 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
880 uint16_t header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN)
881 ? T2T_LONG_NDEF_LEN_FIELD_LEN
882 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
883 uint16_t num_ndef_bytes;
884 uint16_t total_ndef_bytes;
885 uint16_t last_ndef_byte_offset;
886 uint16_t terminator_tlv_byte_index;
887 tNFC_STATUS status;
888 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800889
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800890 total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
891 num_ndef_bytes = 0;
892 last_ndef_byte_offset = p_t2t->ndef_header_offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800893
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800894 /* Locate NDEF final block based on the size of new NDEF Message */
895 while (num_ndef_bytes < total_ndef_bytes) {
896 if (rw_t2t_is_lock_res_byte((uint16_t)(last_ndef_byte_offset)) == false)
897 num_ndef_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800898
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800899 last_ndef_byte_offset++;
900 }
901 p_t2t->ndef_last_block_num =
902 (uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
903 block = p_t2t->ndef_last_block_num;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800904
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800905 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
906 /* Read NDEF last block before updating */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800907 status = rw_t2t_read(block);
908 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800909 if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
910 /* Locate Terminator TLV Block */
911 total_ndef_bytes++;
912 terminator_tlv_byte_index = last_ndef_byte_offset;
913
914 while (num_ndef_bytes < total_ndef_bytes) {
915 if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
916 false)
917 num_ndef_bytes++;
918
919 terminator_tlv_byte_index++;
920 }
921
922 p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
923 } else {
924 /* No space for Terminator TLV */
925 p_t2t->terminator_byte_index = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800926 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800927 }
928 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800929}
930
931/*******************************************************************************
932**
933** Function rw_t2t_read_terminator_tlv_block
934**
935** Description This function will read the block where terminator tlv will
936** be added later
937**
938** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
939**
940*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800941tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
942 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
943 tNFC_STATUS status;
944 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800945
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800946 /* Send read command to read base block (Block % 4==0) where this block is
947 * also read as part of 16 bytes */
948 block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
949 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800950
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800951 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
952 /* Read the block where Terminator TLV may be added later during NDEF Write
953 * operation */
954 status = rw_t2t_read(block);
955 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800956}
957
958/*******************************************************************************
959**
960** Function rw_t2t_read_ndef_next_block
961**
962** Description This function will read the tag block passed as argument
963**
964** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
965**
966*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800967tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block) {
968 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
969 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800970
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800971 /* Send read command to read base block (Block % 4==0) where this block is
972 * also read as part of 16 bytes */
973 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800974
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800975 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
976 /* Read the block */
977 status = rw_t2t_read(block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800978
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800979 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800980}
981
982/*******************************************************************************
983**
984** Function rw_t2t_is_read_before_write_block
985**
986** Description This function will check if the block has to be read before
987** writting to avoid over writting in to lock/reserved bytes
988** present in the block.
989** If no bytes in the block can be overwritten it moves in to
990** next block and check. Finally it finds a block where part of
991** ndef bytes can exist and check if the whole block can be
992** updated or only part of block can be modified.
993**
994** Returns TRUE, if the block returned should be read before writting
995** FALSE, if the block need not be read as it was already
996** read or during NDEF write we may completely overwrite
997** the block and there is no reserved or locked bytes in
998** that block
999**
1000*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001001static bool rw_t2t_is_read_before_write_block(uint16_t block,
1002 uint16_t* p_block_to_read) {
1003 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1004 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1005 uint8_t count;
1006 uint8_t index;
1007 uint16_t tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1008 bool read_before_write = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001009
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001010 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1011 /* First NDEF block is already read */
1012 read_before_write = false;
1013 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
1014 } else if (block == p_t2t->ndef_last_block_num) {
1015 /* Last NDEF block is already read */
1016 read_before_write = false;
1017 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1018 } else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) {
1019 /* Terminator tlv block is already read */
1020 read_before_write = false;
1021 memcpy(p_t2t->ndef_read_block, p_t2t->terminator_tlv_block, T2T_BLOCK_SIZE);
1022 } else {
1023 count = 0;
1024 while (block < tag_size) {
1025 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001026
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001027 while (index < T2T_BLOCK_SIZE) {
1028 /* check if it is a reserved or locked byte */
1029 if (rw_t2t_is_lock_res_byte(
1030 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1031 count++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001032 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001033 index++;
1034 }
1035 if (count == T2T_BLOCK_SIZE) {
1036 /* All the bytes in the block are free to NDEF write */
1037 read_before_write = false;
1038 break;
1039 } else if (count == 0) {
1040 /* The complete block is not free for NDEF write */
1041 index = 0;
1042 block++;
1043 } else {
1044 /* The block has reseved byte (s) or locked byte (s) or both */
1045 read_before_write = true;
1046 break;
1047 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001048 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001049 }
1050 /* Return the block to read next before NDEF write */
1051 *p_block_to_read = block;
1052 return read_before_write;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001053}
1054
1055/*******************************************************************************
1056**
1057** Function rw_t2t_write_ndef_first_block
1058**
1059** Description This function will write the first NDEF block with Length
1060** field reset to zero.
1061** Also after writting NDEF this function may be called to
1062** update new NDEF length
1063**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001064** Returns NCI_STATUS_OK, if write was started.
1065** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001066**
1067*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001068tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len, bool b_update_len) {
1069 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1070 uint8_t new_lengthfield_len;
1071 uint8_t write_block[4];
1072 uint8_t block;
1073 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1074 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1075 tNFC_STATUS status;
1076 uint8_t length_field[3];
1077 uint8_t index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001078
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001079 p_t2t->work_offset = 0;
1080 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1081 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1082 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1083 if (new_lengthfield_len == 3) {
1084 /* New NDEF is Long NDEF */
1085 if (msg_len == 0) {
1086 /* Clear NDEF length field */
1087 length_field[0] = 0x00;
1088 length_field[1] = 0x00;
1089 length_field[2] = 0x00;
1090 } else {
1091 /* Update NDEF length field with new NDEF Msg len */
1092 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1093 length_field[1] = (uint8_t)(msg_len >> 8);
1094 length_field[2] = (uint8_t)(msg_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001095 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001096 } else {
1097 /* New NDEF is Short NDEF */
1098 length_field[0] = (uint8_t)(msg_len);
1099 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001100
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001101 /* updating ndef_first_block with new ndef message */
1102 memcpy(write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001103
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001104 index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1105 block = (uint8_t)(p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001106
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001107 while (p_t2t->work_offset == 0 && block < total_blocks) {
1108 /* update length field */
1109 while (index < T2T_BLOCK_SIZE &&
1110 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1111 if (rw_t2t_is_lock_res_byte(
1112 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1113 write_block[index] = length_field[p_t2t->work_offset];
1114 p_t2t->work_offset++;
1115 }
1116 index++;
1117 if (p_t2t->work_offset == new_lengthfield_len) {
1118 break;
1119 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001120 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001121 /* If more space in this block then add ndef message */
1122 while (index < T2T_BLOCK_SIZE &&
1123 p_t2t->work_offset <
1124 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1125 if (rw_t2t_is_lock_res_byte(
1126 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1127 write_block[index] =
1128 p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1129 p_t2t->work_offset++;
1130 }
1131 index++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001132 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001133 if (p_t2t->work_offset == 0) {
1134 /* If no bytes are written move to next block */
1135 index = 0;
1136 block++;
1137 if (block == p_t2t->ndef_last_block_num) {
1138 memcpy(write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1139 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001140 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001141 }
1142 if (p_t2t->work_offset == 0) {
1143 status = NFC_STATUS_FAILED;
1144 } else {
1145 rw_t2t_update_cb(block, write_block, b_update_len);
1146 /* Update the identified block with newly prepared data */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001147 status = rw_t2t_write(block, write_block);
1148 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001149 p_t2t->b_read_data = false;
1150 }
1151 }
1152 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001153}
1154
1155/*******************************************************************************
1156**
1157** Function rw_t2t_write_ndef_next_block
1158**
1159** Description This function can be called to write an NDEF message block
1160**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001161** Returns NCI_STATUS_OK, if write was started.
1162** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001163**
1164*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001165tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block, uint16_t msg_len,
1166 bool b_update_len) {
1167 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1168 uint8_t new_lengthfield_len;
1169 uint8_t write_block[4];
1170 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1171 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1172 uint16_t initial_offset;
1173 uint8_t length_field[3];
1174 uint8_t index;
1175 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001176
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001177 /* Write NDEF Message */
1178 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1179 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1180 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001181
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001182 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001183
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001184 memcpy(write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001185
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001186 if (p_t2t->work_offset >= new_lengthfield_len) {
1187 /* Length field is updated, write ndef message field */
1188 initial_offset = p_t2t->work_offset;
1189 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1190 while (index < T2T_BLOCK_SIZE &&
1191 p_t2t->work_offset <
1192 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1193 if (rw_t2t_is_lock_res_byte(
1194 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1195 write_block[index] =
1196 p_t2t
1197 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1198 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001199 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001200 index++;
1201 }
1202 if (p_t2t->work_offset == initial_offset) {
1203 index = 0;
1204 block++;
1205 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001206 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001207 } else {
1208 /* Complete writting Length field and then write ndef message */
1209 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1210 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1211 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1212 if (new_lengthfield_len == 3) {
1213 /* New NDEF is Long NDEF */
1214 if (msg_len == 0) {
1215 length_field[0] = 0x00;
1216 length_field[1] = 0x00;
1217 length_field[2] = 0x00;
1218 } else {
1219 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1220 length_field[1] = (uint8_t)(msg_len >> 8);
1221 length_field[2] = (uint8_t)(msg_len);
1222 }
1223 } else {
1224 /* New NDEF is short NDEF */
1225 length_field[0] = (uint8_t)(msg_len);
1226 }
1227 initial_offset = p_t2t->work_offset;
1228 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1229 /* Update length field */
1230 while (index < T2T_BLOCK_SIZE &&
1231 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1232 if (rw_t2t_is_lock_res_byte(
1233 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1234 write_block[index] = length_field[p_t2t->work_offset];
1235 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001236 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001237 index++;
1238 if (p_t2t->work_offset == new_lengthfield_len) {
1239 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001240 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001241 }
1242 /* Update ndef message field */
1243 while (index < T2T_BLOCK_SIZE &&
1244 p_t2t->work_offset <
1245 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1246 if (rw_t2t_is_lock_res_byte(
1247 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1248 write_block[index] =
1249 p_t2t
1250 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1251 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001252 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001253 index++;
1254 }
1255 if (p_t2t->work_offset == initial_offset) {
1256 index = 0;
1257 block++;
1258 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001259 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001260 }
1261 if (p_t2t->work_offset == initial_offset) {
1262 status = NFC_STATUS_FAILED;
1263 } else {
1264 rw_t2t_update_cb(block, write_block, b_update_len);
1265 /* Write the NDEF Block */
1266 status = rw_t2t_write(block, write_block);
1267 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001268
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001269 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001270}
1271
1272/*******************************************************************************
1273**
1274** Function rw_t2t_update_cb
1275**
1276** Description This function can be called to write an NDEF message block
1277**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001278** Returns NCI_STATUS_OK, if write was started.
1279** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001280**
1281*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001282static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
1283 bool b_update_len) {
1284 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1285 uint8_t new_lengthfield_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001286
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001287 /* Write NDEF Message */
1288 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1289 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1290 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001291
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001292 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1293 /* Update ndef first block if the 'block' points to ndef first block */
1294 memcpy(p_t2t->ndef_first_block, p_write_block, T2T_BLOCK_SIZE);
1295 }
1296 if (p_t2t->terminator_byte_index / T2T_BLOCK_SIZE == block) {
1297 /* Update terminator block if the 'block' points to terminator tlv block */
1298 memcpy(p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1299 }
1300 if (b_update_len == false) {
1301 if (block == p_t2t->ndef_last_block_num) {
1302 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1303 p_t2t->work_offset = 0;
1304 /* Update ndef final block if the 'block' points to ndef final block */
1305 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
1306 } else {
1307 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001308 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001309 } else {
1310 if (block == p_t2t->ndef_last_block_num) {
1311 /* Update the backup of Ndef final block TLV block */
1312 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001313 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001314
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001315 if (p_t2t->work_offset >= new_lengthfield_len) {
1316 if (p_t2t->terminator_byte_index != 0) {
1317 /* Add Terminator TLV as part of NDEF Write operation */
1318 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1319 } else {
1320 /* Skip adding Terminator TLV */
1321 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1322 }
1323 } else {
1324 /* Part of NDEF Message Len should be added in the next block */
1325 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001326 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001327 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001328}
1329
1330/*******************************************************************************
1331**
1332** Function rw_t2t_get_ndef_flags
1333**
1334** Description Prepare NDEF Flags
1335**
1336** Returns NDEF Flag value
1337**
1338*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001339static uint8_t rw_t2t_get_ndef_flags(void) {
1340 uint8_t flags = 0;
1341 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1342 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001343
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001344 flags |= RW_NDEF_FL_SUPPORTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001345
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001346 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) ||
1347 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1348 flags |= RW_NDEF_FL_FORMATABLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001349
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001350 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1351 flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001352
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001353 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1354 (p_ret->b_otp)) {
1355 /* Set otp flag */
1356 flags |= RW_NDEF_FL_OTP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001357
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001358 /* Set Read only flag if otp tag already has NDEF Message */
1359 if (p_t2t->ndef_msg_len) flags |= RW_NDEF_FL_READ_ONLY;
1360 }
1361 return flags;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001362}
1363
1364/*******************************************************************************
1365**
1366** Function rw_t2t_get_ndef_max_size
1367**
1368** Description Calculate maximum size of NDEF message that can be written
1369** on to the tag
1370**
1371** Returns Maximum size of NDEF Message
1372**
1373*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001374static uint16_t rw_t2t_get_ndef_max_size(void) {
1375 uint16_t offset;
1376 uint8_t xx;
1377 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1378 uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
1379 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
1380 p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001381
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001382 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1383 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001384
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001385 offset = p_t2t->ndef_msg_offset;
1386 p_t2t->max_ndef_msg_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001387
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001388 if ((tag_size < T2T_STATIC_SIZE) ||
1389 (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
1390 ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
1391 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
1392 /* Tag not formated, assume static tag */
1393 p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
1394 T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001395 return p_t2t->max_ndef_msg_len;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001396 }
1397
1398 /* Starting from NDEF Message offset find the first locked data byte */
1399 while (offset < tag_size) {
1400 if (rw_t2t_is_lock_res_byte((uint16_t)offset) == false) {
1401 if (rw_t2t_is_read_only_byte((uint16_t)offset) == true) break;
1402 p_t2t->max_ndef_msg_len++;
1403 }
1404 offset++;
1405 }
1406 /* NDEF Length field length changes based on NDEF size */
1407 if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
1408 ((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
1409 T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
1410 p_t2t->max_ndef_msg_len -=
1411 (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1412 ? 1
1413 : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1414 }
1415 return p_t2t->max_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001416}
1417
1418/*******************************************************************************
1419**
1420** Function rw_t2t_add_terminator_tlv
1421**
1422** Description This function will add terminator TLV after NDEF Message
1423**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001424** Returns NCI_STATUS_OK, if write was started.
1425** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001426**
1427*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001428tNFC_STATUS rw_t2t_add_terminator_tlv(void) {
1429 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1430 tNFC_STATUS status;
1431 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001432
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001433 /* Add Terminator TLV after NDEF Message */
1434 p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
1435 TAG_TERMINATOR_TLV;
1436 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001437
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001438 block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
1439 status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001440
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001441 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001442}
1443
1444/*******************************************************************************
1445**
1446** Function rw_t2t_handle_ndef_read_rsp
1447**
1448** Description This function handles reading an NDEF message.
1449**
1450** Returns none
1451**
1452*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001453static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data) {
1454 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1455 tRW_READ_DATA evt_data;
1456 uint16_t len;
1457 uint16_t offset;
1458 bool failed = false;
1459 bool done = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001460
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001461 /* On the first read, adjust for any partial block offset */
1462 offset = 0;
1463 len = T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001464
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001465 if (p_t2t->work_offset == 0) {
1466 /* The Ndef Message offset may be present in the read 16 bytes */
1467 offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1468 }
1469
1470 /* Skip all reserved and lock bytes */
1471 while ((offset < len) && (p_t2t->work_offset < p_t2t->ndef_msg_len))
1472
1473 {
1474 if (rw_t2t_is_lock_res_byte(
1475 (uint16_t)(offset + p_t2t->block_read * T2T_BLOCK_LEN)) == false) {
1476 /* Collect the NDEF Message */
1477 p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1478 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001479 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001480 offset++;
1481 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001482
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001483 if (p_t2t->work_offset >= p_t2t->ndef_msg_len) {
1484 done = true;
1485 p_t2t->ndef_status = T2T_NDEF_READ;
1486 } else {
1487 /* Read next 4 blocks */
1488 if (rw_t2t_read((uint16_t)(p_t2t->block_read + T2T_READ_BLOCKS)) !=
1489 NFC_STATUS_OK)
1490 failed = true;
1491 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001492
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001493 if (failed || done) {
1494 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1495 evt_data.p_data = NULL;
1496 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001497 tRW_DATA rw_data;
1498 rw_data.data = evt_data;
1499 (*rw_cb.p_cback)(RW_T2T_NDEF_READ_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001500 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001501}
1502
1503/*******************************************************************************
1504**
1505** Function rw_t2t_handle_ndef_write_rsp
1506**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001507** Description Handle response received to reading (or part of) NDEF
1508** message.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001509**
1510** Returns none
1511**
1512*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001513static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data) {
1514 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1515 tRW_READ_DATA evt_data;
1516 bool failed = false;
1517 bool done = false;
1518 uint16_t block;
1519 uint8_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001520
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001521 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001522 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1523
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001524 /* Backup the read NDEF first block */
1525 memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1526 /* Read ndef final block */
1527 if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
1528 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001529
1530 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1531
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001532 offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
1533 T2T_BLOCK_SIZE;
1534 /* Backup the read NDEF final block */
1535 memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1536 if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
1537 p_t2t->ndef_last_block_num) {
1538 /* If Terminator TLV will reside on the NDEF Final block */
1539 memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
1540 T2T_BLOCK_LEN);
1541 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1542 failed = true;
1543 } else if (p_t2t->terminator_byte_index != 0) {
1544 /* If there is space for Terminator TLV and if it will reside outside
1545 * NDEF Final block */
1546 if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
1547 } else {
1548 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1549 failed = true;
1550 }
1551 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001552
1553 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1554
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001555 offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
1556 p_t2t->block_read) *
1557 T2T_BLOCK_SIZE);
1558 /* Backup the read Terminator TLV block */
1559 memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001560
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001561 /* Write the first block for new NDEF Message */
1562 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1563 failed = true;
1564 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001565
1566 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1567
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001568 offset = (uint8_t)(p_t2t->ndef_read_block_num - p_t2t->block_read) *
1569 T2T_BLOCK_SIZE;
1570 /* Backup read block */
1571 memcpy(p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001572
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001573 /* Update the block with new NDEF Message */
1574 if (rw_t2t_write_ndef_next_block(p_t2t->ndef_read_block_num, 0x0000,
1575 false) != NFC_STATUS_OK)
1576 failed = true;
1577 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001578
1579 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1580 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001581 if (rw_t2t_is_read_before_write_block(
1582 (uint16_t)(p_t2t->block_written + 1), &block) == true) {
1583 p_t2t->ndef_read_block_num = block;
1584 /* If only part of the block is going to be updated read the block to
1585 retain previous data for
1586 unchanged part of the block */
1587 if (rw_t2t_read_ndef_next_block(block) != NFC_STATUS_OK) failed = true;
1588 } else {
1589 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK) {
1590 /* Directly write the block with new NDEF contents as whole block is
1591 * going to be updated */
1592 if (rw_t2t_write_ndef_next_block(block, p_t2t->new_ndef_msg_len,
1593 true) != NFC_STATUS_OK)
1594 failed = true;
1595 } else {
1596 /* Directly write the block with new NDEF contents as whole block is
1597 * going to be updated */
1598 if (rw_t2t_write_ndef_next_block(block, 0x0000, false) !=
1599 NFC_STATUS_OK)
1600 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001601 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001602 }
1603 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001604
1605 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001606 /* Write the next block for new NDEF Message */
1607 p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1608 if (rw_t2t_is_read_before_write_block((uint16_t)(p_t2t->ndef_write_block),
1609 &block) == true) {
1610 /* If only part of the block is going to be updated read the block to
1611 retain previous data for
1612 part of the block thats not going to be changed */
1613 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1614 if (rw_t2t_read(block) != NFC_STATUS_OK) failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001615
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001616 } else {
1617 /* Update NDEF Message Length in the Tag */
1618 if (rw_t2t_write_ndef_first_block(p_t2t->new_ndef_msg_len, true) !=
1619 NFC_STATUS_OK)
1620 failed = true;
1621 }
1622 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001623
1624 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001625 /* Backup read block */
1626 memcpy(p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001627
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001628 /* Update the block with new NDEF Message */
1629 if (rw_t2t_write_ndef_next_block(p_t2t->block_read,
1630 p_t2t->new_ndef_msg_len,
1631 true) == NFC_STATUS_OK)
1632 p_t2t->ndef_write_block = p_t2t->block_read + 1;
1633 else
1634 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001635
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001636 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001637
1638 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001639 if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
1640 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001641
1642 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001643 done = true;
1644 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001645
1646 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001647 break;
1648 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001649
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001650 if (failed || done) {
1651 evt_data.p_data = NULL;
1652 /* NDEF WRITE Operation is done, inform up the stack */
1653 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1654 if (done) {
1655 if ((p_t2t->ndef_msg_len >= 0x00FF) &&
1656 (p_t2t->new_ndef_msg_len < 0x00FF)) {
1657 p_t2t->ndef_msg_offset -= 2;
1658 } else if ((p_t2t->new_ndef_msg_len >= 0x00FF) &&
1659 (p_t2t->ndef_msg_len < 0x00FF)) {
1660 p_t2t->ndef_msg_offset += 2;
1661 }
1662 p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001663 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001664 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001665 tRW_DATA rw_data;
1666 rw_data.data = evt_data;
1667 (*rw_cb.p_cback)(RW_T2T_NDEF_WRITE_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001668 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001669}
1670
1671/*******************************************************************************
1672**
1673** Function rw_t2t_get_tag_size
1674**
1675** Description This function calculates tag data area size from data read
1676** from block with version number
1677**
1678** Returns TMS of the tag
1679**
1680*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001681static uint8_t rw_t2t_get_tag_size(uint8_t* p_data) {
1682 uint16_t LchunkSize = 0;
1683 uint16_t Num_LChuncks = 0;
1684 uint16_t tms = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001685
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001686 LchunkSize = (uint16_t)p_data[2] << 8 | p_data[3];
1687 Num_LChuncks = (uint16_t)p_data[4] << 8 | p_data[5];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001688
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001689 tms = (uint16_t)(LchunkSize * Num_LChuncks);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001690
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001691 tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001692
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001693 tms /= 0x08;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001694
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001695 return (uint8_t)tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001696}
1697
1698/*******************************************************************************
1699**
1700** Function rw_t2t_handle_config_tag_readonly
1701**
1702** Description This function handles configure type 2 tag as read only
1703**
1704** Returns none
1705**
1706*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001707static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data) {
1708 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1709 tNFC_STATUS status = NFC_STATUS_FAILED;
1710 bool b_notify = false;
1711 uint8_t write_block[T2T_BLOCK_SIZE];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001712 bool b_pending = false;
1713 uint8_t read_lock = 0;
1714 uint8_t num_locks = 0;
1715 uint16_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001716
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001717 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001718 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1719
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001720 /* First soft lock the tag */
1721 rw_t2t_soft_lock_tag();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001722
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001723 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001724
1725 case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1726
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001727 /* Successfully soft locked! Update Tag header for future reference */
1728 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1729 if (!p_t2t->b_hard_lock) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001730 /* Tag configuration complete */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001731 status = NFC_STATUS_OK;
Ruchi Kandoi4a179642017-01-04 10:04:48 -08001732 b_notify = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001733 break;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001734 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001735
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001736 /* Coverity: [FALSE-POSITIVE error] intended fall through */
1737 /* Missing break statement between cases in switch statement */
1738 /* fall through */
1739 case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001740
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001741 num_locks = 0;
1742
1743 while (num_locks < p_t2t->num_lockbytes) {
1744 if (p_t2t->lockbyte[num_locks].lock_status ==
1745 RW_T2T_LOCK_UPDATE_INITIATED) {
1746 /* Update control block as one or more dynamic lock byte (s) are set
1747 */
1748 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1749 }
1750 if (!b_pending &&
1751 p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
1752 /* One or more dynamic lock bits are not set */
1753 b_pending = true;
1754 read_lock = num_locks;
1755 }
1756 num_locks++;
1757 }
1758
1759 if (b_pending) {
1760 /* Read the block where dynamic lock bits are present to avoid writing
1761 * to NDEF bytes in the same block */
1762 offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
1763 p_t2t->lockbyte[read_lock].byte_index;
1764 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1765 status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
1766 } else {
1767 /* Now set Static lock bits as no more dynamic lock bits to set */
1768
1769 /* Copy the internal bytes */
1770 memcpy(write_block,
1771 &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
1772 T2T_INTERNAL_BYTES_LEN);
1773 /* Set all Static lock bits */
1774 write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1775 write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1776 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1777 status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1778 }
1779 break;
1780
1781 case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1782 /* Now set the dynamic lock bits present in the block read now */
1783 status = rw_t2t_set_dynamic_lock_bits(p_data);
1784 break;
1785
1786 case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1787 /* Tag configuration complete */
1788 status = NFC_STATUS_OK;
1789 b_notify = true;
1790 break;
1791 }
1792
1793 if (status != NFC_STATUS_OK || b_notify) {
1794 /* Notify upper layer the result of Configuring Tag as Read only */
Myles Watson1361d522017-09-26 13:39:54 -07001795 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001796 evt.status = status;
1797 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001798 (*rw_cb.p_cback)(RW_T2T_SET_TAG_RO_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001799 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001800}
1801
1802/*******************************************************************************
1803**
1804** Function rw_t2t_handle_format_tag_rsp
1805**
1806** Description This function handles formating a type 2 tag
1807**
1808** Returns none
1809**
1810*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001811static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001812 uint8_t* p;
1813 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1814 tNFC_STATUS status = NFC_STATUS_FAILED;
1815 uint16_t version_no;
1816 const tT2T_INIT_TAG* p_ret;
1817 uint8_t tms;
1818 uint8_t next_block = T2T_FIRST_DATA_BLOCK + 1;
1819 uint16_t addr, locked_area;
1820 bool b_notify = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001821
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001822 p = p_t2t->ndef_final_block;
1823 UINT8_TO_BE_STREAM(p, p_t2t->tlv_value[2]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001824
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001825 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001826 case RW_T2T_SUBSTATE_WAIT_READ_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001827 /* Start format operation */
1828 status = rw_t2t_format_tag();
1829 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001830
1831 case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1832
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001833 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1834 p_t2t->b_read_data = true;
1835 version_no = (uint16_t)p_data[0] << 8 | p_data[1];
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001836 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no);
1837 if (p_ret != NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001838 /* Valid Version Number */
1839 if (p_ret->b_calc_cc) /* Calculate tag size from Version Information */
1840 tms = rw_t2t_get_tag_size(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001841
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001842 else
1843 /* Tag size from Look up table */
1844 tms = p_ret->tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001845
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001846 /* Set CC with the Tag size from look up table or from calculated value
1847 */
1848 status = rw_t2t_set_cc(tms);
1849 }
1850 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001851
1852 case RW_T2T_SUBSTATE_WAIT_SET_CC:
1853
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001854 version_no = (uint16_t)p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1855 if ((version_no == 0) ||
1856 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) ==
1857 NULL) ||
1858 (!p_ret->b_multi_version) || (!p_ret->b_calc_cc)) {
1859 /* Currently Formating a non blank tag or a blank tag with manufacturer
1860 * has only one variant of tag. Set Null NDEF TLV and complete Format
1861 * Operation */
1862 next_block = T2T_FIRST_DATA_BLOCK;
1863 p = p_t2t->ndef_final_block;
1864 } else {
1865 addr = (uint16_t)(
1866 ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1867 ((uint16_t)p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) +
1868 T2T_STATIC_SIZE);
1869 locked_area = ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1870 ((uint16_t)p_t2t->tag_data[6]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001871
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001872 status = rw_t2t_set_lock_tlv(addr, p_t2t->tag_data[7], locked_area);
1873 if (status == NFC_STATUS_REJECTED) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001874 /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format
1875 * Operation */
1876 next_block = T2T_FIRST_DATA_BLOCK;
1877 p = p_t2t->ndef_final_block;
1878 } else
1879 break;
1880 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001881
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001882 /* falls through */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001883 case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
1884
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001885 /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
1886 UINT8_TO_BE_STREAM(p, TAG_NDEF_TLV);
1887 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001888
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001889 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1890 (!p_ret->b_otp)) {
1891 UINT8_TO_BE_STREAM(p, TAG_TERMINATOR_TLV);
1892 } else
1893 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001894
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001895 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
1896 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001897 status = rw_t2t_write(next_block, p_t2t->ndef_final_block);
1898 if (status == NFC_STATUS_OK) p_t2t->b_read_data = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001899 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001900
1901 case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001902 /* Tag Formated successfully */
1903 status = NFC_STATUS_OK;
1904 b_notify = true;
1905 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001906
1907 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001908 break;
1909 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001910
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001911 if (status != NFC_STATUS_OK || b_notify) {
1912 /* Notify upper layer the result of Format op */
Myles Watson1361d522017-09-26 13:39:54 -07001913 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001914 evt.status = status;
1915 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001916 (*rw_cb.p_cback)(RW_T2T_FORMAT_CPLT_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001917 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001918}
1919
1920/*******************************************************************************
1921**
1922** Function rw_t2t_update_attributes
1923**
1924** Description This function will update attribute for the current segment
1925** based on lock and reserved bytes
1926**
1927** Returns None
1928**
1929*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001930static void rw_t2t_update_attributes(void) {
1931 uint8_t count = 0;
1932 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1933 uint16_t lower_offset;
1934 uint16_t upper_offset;
1935 uint16_t offset;
1936 uint8_t num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001937
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001938 /* Prepare attr for the current segment */
1939 memset(p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001940
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001941 /* calculate offset where the current segment starts in the tag */
1942 lower_offset = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
1943 /* calculate offset where the current segment ends in the tag */
1944 upper_offset = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001945
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001946 /* check offset of lock bytes in the tag and update p_t2t->attr
1947 * for every lock byte that is present in the current segment */
1948 count = 0;
1949 while (count < p_t2t->num_lockbytes) {
1950 offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset +
1951 p_t2t->lockbyte[count].byte_index;
1952 if (offset >= lower_offset && offset < upper_offset) {
1953 /* Calculate offset in the current segment as p_t2t->attr is prepared for
1954 * one segment only */
1955 offset %= RW_T2T_SEGMENT_BYTES;
1956 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1957 * lock/reserved byte or not
1958 * So, each array element in p_t2t->attr covers two blocks in the tag as
1959 * T2 block size is 4 and array element size is 8
1960 * Set the corresponding bit in attr to indicate - reserved byte */
1961 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1962 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001963 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001964 count++;
1965 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001966
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001967 /* Search reserved bytes identified by all memory tlvs present in the tag */
1968 count = 0;
1969 while (count < p_t2t->num_mem_tlvs) {
1970 /* check the offset of reserved bytes in the tag and update p_t2t->attr
1971 * for every reserved byte that is present in the current segment */
1972 num_bytes = 0;
1973 while (num_bytes < p_t2t->mem_tlv[count].num_bytes) {
1974 offset = p_t2t->mem_tlv[count].offset + num_bytes;
1975 if (offset >= lower_offset && offset < upper_offset) {
1976 /* Let offset represents offset in the current segment as p_t2t->attr is
1977 * prepared for one segment only */
1978 offset %= RW_T2T_SEGMENT_BYTES;
1979 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1980 * lock/reserved byte or not
1981 * So, each array element in p_t2t->attr covers two blocks in the tag as
1982 * T2 block size is 4 and array element size is 8
1983 * Set the corresponding bit in attr to indicate - reserved byte */
1984 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1985 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
1986 }
1987 num_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001988 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001989 count++;
1990 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001991}
1992
1993/*******************************************************************************
1994**
1995** Function rw_t2t_get_lock_bits_for_segment
1996**
1997** Description This function returns the offset of lock bits associated for
1998** the specified segment
1999**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002000** Parameters: segment: The segment number to which lock bits are
2001** associated
2002** p_start_byte: The offset of lock byte that contains the
2003** first lock bit for the segment
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002004** p_start_bit: The offset of the lock bit in the lock byte
2005**
2006** p_end_byte: The offset of the last bit associcated to the
2007** segment
2008**
2009** Returns Total number of lock bits assigned to the specified segment
2010**
2011*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002012static uint8_t rw_t2t_get_lock_bits_for_segment(uint8_t segment,
2013 uint8_t* p_start_byte,
2014 uint8_t* p_start_bit,
2015 uint8_t* p_end_byte) {
2016 uint8_t total_bits = 0;
2017 uint16_t byte_count = 0;
2018 uint16_t lower_offset, upper_offset;
2019 uint8_t num_dynamic_locks = 0;
2020 uint8_t bit_count = 0;
2021 uint8_t bytes_locked_per_bit;
2022 uint8_t num_bits;
2023 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2024 bool b_all_bits_are_locks = true;
2025 uint16_t tag_size;
2026 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002027
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002028 tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
2029 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002030
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002031 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2032 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002033
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002034 lower_offset = segment * RW_T2T_SEGMENT_BYTES;
2035 if (segment == 0) {
2036 lower_offset += T2T_STATIC_SIZE;
2037 }
2038 upper_offset = (segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002039
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002040 byte_count = T2T_STATIC_SIZE;
2041 if (tag_size < upper_offset) {
2042 upper_offset = tag_size;
2043 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002044
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002045 *p_start_byte = num_dynamic_locks;
2046 *p_start_bit = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002047
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002048 while ((byte_count <= lower_offset) &&
2049 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2050 bytes_locked_per_bit =
2051 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2052 .bytes_locked_per_bit;
2053 /* Number of bits in the current lock byte */
2054 b_all_bits_are_locks =
2055 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2056 TAG_BITS_PER_BYTE <=
2057 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2058 .num_bits);
2059 num_bits =
2060 b_all_bits_are_locks
2061 ? TAG_BITS_PER_BYTE
2062 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2063 .num_bits %
2064 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002065
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002066 if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset) {
2067 /* Skip this lock byte as it covers different segment */
2068 byte_count += bytes_locked_per_bit * num_bits;
2069 num_dynamic_locks++;
2070 } else {
2071 bit_count = 0;
2072 while (bit_count < num_bits) {
2073 byte_count += bytes_locked_per_bit;
2074 if (byte_count > lower_offset) {
2075 /* First lock bit that is used to lock this segment */
2076 *p_start_byte = num_dynamic_locks;
2077 *p_end_byte = num_dynamic_locks;
2078 *p_start_bit = bit_count;
2079 bit_count++;
2080 total_bits = 1;
2081 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002082 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002083 bit_count++;
2084 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002085 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002086 }
2087 if (num_dynamic_locks == p_t2t->num_lockbytes) {
2088 return 0;
2089 }
2090 while ((byte_count < upper_offset) &&
2091 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2092 bytes_locked_per_bit =
2093 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2094 .bytes_locked_per_bit;
2095 /* Number of bits in the current lock byte */
2096 b_all_bits_are_locks =
2097 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2098 TAG_BITS_PER_BYTE <=
2099 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2100 .num_bits);
2101 num_bits =
2102 b_all_bits_are_locks
2103 ? TAG_BITS_PER_BYTE
2104 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2105 .num_bits %
2106 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002107
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002108 if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count <
2109 upper_offset) {
2110 /* Collect all lock bits that covers the current segment */
2111 byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2112 total_bits += num_bits - bit_count;
2113 bit_count = 0;
2114 *p_end_byte = num_dynamic_locks;
2115 num_dynamic_locks++;
2116 } else {
2117 /* The last lock byte that covers the current segment */
2118 bit_count = 0;
2119 while (bit_count < num_bits) {
2120 /* The last lock bit that is used to lock this segment */
2121 byte_count += bytes_locked_per_bit;
2122 if (byte_count >= upper_offset) {
2123 *p_end_byte = num_dynamic_locks;
2124 total_bits += (bit_count + 1);
2125 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002126 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002127 bit_count++;
2128 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002129 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002130 }
2131 return total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002132}
2133
2134/*******************************************************************************
2135**
2136** Function rw_t2t_update_lock_attributes
2137**
2138** Description This function will check if the tag index passed as
2139** argument is a locked byte and return TRUE or FALSE
2140**
2141** Parameters: index, the index of the byte in the tag
2142**
2143**
2144** Returns TRUE, if the specified index in the tag is a locked or
2145** reserved or otp byte
2146** FALSE, otherwise
2147**
2148*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002149static void rw_t2t_update_lock_attributes(void) {
2150 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2151 uint8_t xx = 0;
2152 uint8_t num_static_lock_bytes = 0;
2153 uint8_t num_dyn_lock_bytes = 0;
2154 uint8_t bits_covered = 0;
2155 uint8_t bytes_covered = 0;
2156 uint8_t block_count = 0;
2157 bool b_all_bits_are_locks = true;
2158 uint8_t bytes_locked_per_lock_bit;
2159 uint8_t start_lock_byte;
2160 uint8_t start_lock_bit;
2161 uint8_t end_lock_byte;
2162 uint8_t num_lock_bits;
2163 uint8_t total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002164
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002165 /* Prepare lock_attr for the current segment */
2166 memset(p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002167
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002168 block_count = 0;
2169 if (p_t2t->segment == 0) {
2170 /* Update lock_attributes based on static lock bytes */
2171 xx = 0;
2172 num_static_lock_bytes = 0;
2173 block_count = 0;
2174 num_lock_bits =
2175 TAG_BITS_PER_BYTE - 1; /* the inner while loop increases xx by 2. need
2176 (-1) to avoid coverity overrun error */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002177
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002178 while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES) {
2179 /* Update lock attribute based on 2 static locks */
2180 while (xx < num_lock_bits) {
2181 p_t2t->lock_attr[block_count] = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002182
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002183 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2184 rw_t2t_mask_bits[xx++]) {
2185 /* If the bit is set then 1 block is locked */
2186 p_t2t->lock_attr[block_count] = 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002187 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002188
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002189 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2190 rw_t2t_mask_bits[xx++]) {
2191 /* If the bit is set then 1 block is locked */
2192 p_t2t->lock_attr[block_count] |= 0xF0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002193 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002194 block_count++;
2195 }
2196 num_static_lock_bytes++;
2197 xx = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002198 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002199 /* UID is always locked, irrespective of the lock value */
2200 p_t2t->lock_attr[0x00] = 0xFF;
2201 }
2202
2203 /* Get lock bits applicable for the current segment */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002204 total_bits = rw_t2t_get_lock_bits_for_segment(
2205 p_t2t->segment, &start_lock_byte, &start_lock_bit, &end_lock_byte);
2206 if (total_bits != 0) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002207 /* update lock_attributes based on current segment using dynamic lock bytes
2208 */
2209 xx = start_lock_bit;
2210 num_dyn_lock_bytes = start_lock_byte;
2211 bits_covered = 0;
2212 bytes_covered = 0;
2213 num_lock_bits = TAG_BITS_PER_BYTE;
2214 p_t2t->lock_attr[block_count] = 0;
2215
2216 while (num_dyn_lock_bytes <= end_lock_byte) {
2217 bytes_locked_per_lock_bit =
2218 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2219 .bytes_locked_per_bit;
2220 /* Find number of bits in the byte are lock bits */
2221 b_all_bits_are_locks =
2222 ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) *
2223 TAG_BITS_PER_BYTE <=
2224 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2225 .num_bits);
2226 num_lock_bits =
2227 b_all_bits_are_locks
2228 ? TAG_BITS_PER_BYTE
2229 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2230 .num_bits %
2231 TAG_BITS_PER_BYTE;
2232
2233 while (xx < num_lock_bits) {
2234 bytes_covered = 0;
2235 while (bytes_covered < bytes_locked_per_lock_bit) {
2236 if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte &
2237 rw_t2t_mask_bits[xx]) {
2238 /* If the bit is set then it is locked */
2239 p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
2240 }
2241 bytes_covered++;
2242 bits_covered++;
2243 if (bits_covered == TAG_BITS_PER_BYTE) {
2244 /* Move to next 8 bytes */
2245 bits_covered = 0;
2246 block_count++;
2247 /* Assume unlocked before updating using locks */
2248 if (block_count < RW_T2T_SEGMENT_SIZE)
2249 p_t2t->lock_attr[block_count] = 0;
2250 }
2251 }
2252 xx++;
2253 }
2254 num_dyn_lock_bytes++;
2255 xx = 0;
2256 }
2257 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002258}
2259
2260/*******************************************************************************
2261**
2262** Function rw_t2t_is_lock_res_byte
2263**
2264** Description This function will check if the tag index passed as
2265** argument is a lock or reserved or otp byte and return
2266** TRUE or FALSE
2267**
2268** Parameters: index, the index of the byte in the tag
2269**
2270**
2271** Returns TRUE, if the specified index in the tag is a locked or
2272** reserved or otp byte
2273** FALSE, otherwise
2274**
2275*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002276static bool rw_t2t_is_lock_res_byte(uint16_t index) {
2277 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002278
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002279 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002280
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002281 if (p_t2t->attr_seg != p_t2t->segment) {
2282 /* Update attributes for the current segment */
2283 rw_t2t_update_attributes();
2284 p_t2t->attr_seg = p_t2t->segment;
2285 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002286
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002287 index = index % RW_T2T_SEGMENT_BYTES;
2288 /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a
2289 * lock/reserved byte or not
2290 * So, each array element in p_t2t->attr covers two blocks in the tag as T2
2291 * block size is 4 and array element size is 8
2292 * Find the block and offset for the index (passed as argument) and Check if
2293 * the offset bit in the
2294 * p_t2t->attr[block/2] is set or not. If the bit is set then it is a
2295 * lock/reserved byte, otherwise not */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002296
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002297 return ((p_t2t->attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0) ? false
2298 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002299}
2300
2301/*******************************************************************************
2302**
2303** Function rw_t2t_is_read_only_byte
2304**
2305** Description This function will check if the tag index passed as
2306** argument is a locked and return
2307** TRUE or FALSE
2308**
2309** Parameters: index, the index of the byte in the tag
2310**
2311**
2312** Returns TRUE, if the specified index in the tag is a locked or
2313** reserved or otp byte
2314** FALSE, otherwise
2315**
2316*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002317static bool rw_t2t_is_read_only_byte(uint16_t index) {
2318 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002319
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002320 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002321
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002322 if (p_t2t->lock_attr_seg != p_t2t->segment) {
2323 /* Update lock attributes for the current segment */
2324 rw_t2t_update_lock_attributes();
2325 p_t2t->lock_attr_seg = p_t2t->segment;
2326 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002327
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002328 index = index % RW_T2T_SEGMENT_BYTES;
2329 /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a
2330 * read only byte or read write byte
2331 * So, each array element in p_t2t->lock_attr covers two blocks of the tag as
2332 * T2 block size is 4 and array element size is 8
2333 * Find the block and offset for the index (passed as argument) and Check if
2334 * the offset bit in
2335 * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a
2336 * read only byte, otherwise read write byte */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002337
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002338 return ((p_t2t->lock_attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0)
2339 ? false
2340 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002341}
2342
2343/*******************************************************************************
2344**
2345** Function rw_t2t_set_dynamic_lock_bits
2346**
2347** Description This function will set dynamic lock bits as part of
2348** configuring tag as read only
2349**
2350** Returns
2351** NFC_STATUS_OK, Command sent to set dynamic lock bits
2352** NFC_STATUS_FAILED: otherwise
2353**
2354*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002355tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data) {
2356 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2357 uint8_t write_block[T2T_BLOCK_SIZE];
2358 uint16_t offset;
2359 uint16_t next_offset;
2360 uint8_t num_bits;
2361 uint8_t next_num_bits;
2362 tNFC_STATUS status = NFC_STATUS_FAILED;
2363 uint8_t num_locks;
2364 uint8_t lock_count;
2365 bool b_all_bits_are_locks = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002366
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002367 num_locks = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002368
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002369 memcpy(write_block, p_data, T2T_BLOCK_SIZE);
2370 while (num_locks < p_t2t->num_lockbytes) {
2371 if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
2372 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
2373 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002374
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002375 /* Check if all bits are lock bits in the byte */
2376 b_all_bits_are_locks =
2377 ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <=
2378 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2379 num_bits =
2380 b_all_bits_are_locks
2381 ? TAG_BITS_PER_BYTE
2382 : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits %
2383 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002384
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002385 write_block[(uint8_t)(offset % T2T_BLOCK_SIZE)] |=
2386 tags_pow(2, num_bits) - 1;
2387 lock_count = num_locks + 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002388
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002389 /* Set all the lock bits in the block using a sing block write command */
2390 while (lock_count < p_t2t->num_lockbytes) {
2391 next_offset =
2392 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset +
2393 p_t2t->lockbyte[lock_count].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002394
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002395 /* Check if all bits are lock bits in the byte */
2396 b_all_bits_are_locks =
2397 ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <=
2398 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2399 next_num_bits =
2400 b_all_bits_are_locks
2401 ? TAG_BITS_PER_BYTE
2402 : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index]
2403 .num_bits %
2404 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002405
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002406 if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE) {
2407 write_block[(uint8_t)(next_offset % T2T_BLOCK_SIZE)] |=
2408 tags_pow(2, next_num_bits) - 1;
2409 } else
2410 break;
2411 lock_count++;
2412 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002413
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002414 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2415 /* send WRITE command to set dynamic lock bits */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002416 status = rw_t2t_write((uint16_t)(offset / T2T_BLOCK_SIZE), write_block);
2417 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002418 while (lock_count > num_locks) {
2419 /* Set update initiated flag to indicate a write command is sent to
2420 * set dynamic lock bits of the block */
2421 p_t2t->lockbyte[lock_count - 1].lock_status =
2422 RW_T2T_LOCK_UPDATE_INITIATED;
2423 lock_count--;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002424 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002425 } else
2426 status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002427
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002428 break;
2429 }
2430 num_locks++;
2431 }
2432
2433 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002434}
2435
2436/*******************************************************************************
2437**
2438** Function rw_t2t_set_lock_tlv
2439**
2440** Description This function will set lock control tlv on the blank
2441** activated type 2 tag based on values read from version block
2442**
2443** Parameters: TAG data memory size
2444**
2445** Returns
2446** NFC_STATUS_OK, Command sent to set Lock TLV
2447** NFC_STATUS_FAILED: otherwise
2448**
2449*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002450tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
2451 uint16_t locked_area_size) {
2452 tNFC_STATUS status = NFC_STATUS_FAILED;
2453 int8_t PageAddr = 0;
2454 int8_t BytePerPage = 0;
2455 int8_t ByteOffset = 0;
2456 uint8_t a;
2457 uint8_t data_block[T2T_BLOCK_SIZE];
2458 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2459 uint8_t* p;
2460 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002461
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002462 for (xx = 15; xx > 0; xx--) {
2463 a = (uint8_t)(addr / xx);
2464 a += (addr % xx) ? 1 : 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002465
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002466 BytePerPage = (int8_t)tags_log2(a);
2467 ByteOffset = (int8_t)(addr - xx * tags_pow(2, BytePerPage));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002468
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002469 if (ByteOffset < 16) {
2470 PageAddr = xx;
2471 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002472 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002473 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002474
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002475 if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16)) {
2476 memset(data_block, 0, T2T_BLOCK_SIZE);
2477 p = data_block;
2478 UINT8_TO_BE_STREAM(p, T2T_TLV_TYPE_LOCK_CTRL);
2479 UINT8_TO_BE_STREAM(p, T2T_TLEN_LOCK_CTRL_TLV);
2480 UINT8_TO_BE_STREAM(p, (PageAddr << 4 | ByteOffset));
2481 UINT8_TO_BE_STREAM(p, num_dyn_lock_bits);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002482
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002483 p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2484 p_t2t->tlv_value[1] = num_dyn_lock_bits;
2485 p_t2t->tlv_value[2] =
2486 (uint8_t)(BytePerPage << 4 | tags_log2(locked_area_size));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002487
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002488 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002489
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002490 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002491 status = rw_t2t_write(T2T_FIRST_DATA_BLOCK, data_block);
2492 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002493 p_t2t->b_read_data = false;
2494 } else
2495 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2496 } else
2497 status = NFC_STATUS_REJECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002498
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002499 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002500}
2501
2502/*******************************************************************************
2503**
2504** Function rw_t2t_set_cc
2505**
2506** Description This function will set Capability Container on the activated
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002507** type 2 tag with default values of CC0, CC1, CC4 and
2508** specified CC3 value
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002509**
2510** Parameters: CC3 value of the tag
2511**
2512** Returns
2513** NFC_STATUS_OK, Command sent to set CC
2514** NFC_STATUS_FAILED: otherwise
2515**
2516*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002517tNFC_STATUS rw_t2t_set_cc(uint8_t tms) {
2518 uint8_t cc_block[T2T_BLOCK_SIZE];
2519 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2520 tNFC_STATUS status = NFC_STATUS_FAILED;
2521 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002522
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002523 memset(cc_block, 0, T2T_BLOCK_SIZE);
2524 memset(p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2525 p = cc_block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002526
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002527 /* Prepare Capability Container */
2528 UINT8_TO_BE_STREAM(p, T2T_CC0_NMN);
2529 UINT8_TO_BE_STREAM(p, T2T_CC1_VNO);
2530 UINT8_TO_BE_STREAM(p, tms);
2531 UINT8_TO_BE_STREAM(p, T2T_CC3_RWA_RW);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002532
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002533 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002534
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002535 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002536 status = rw_t2t_write(T2T_CC_BLOCK, cc_block);
2537 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002538 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2539 p_t2t->b_read_hdr = false;
2540 } else
2541 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002542
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002543 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002544}
2545
2546/*******************************************************************************
2547**
2548** Function rw_t2t_format_tag
2549**
2550** Description This function will format tag based on Manufacturer ID
2551**
2552** Returns
2553** NFC_STATUS_OK, Command sent to format Tag
2554** NFC_STATUS_FAILED: otherwise
2555**
2556*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002557tNFC_STATUS rw_t2t_format_tag(void) {
2558 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2559 const tT2T_INIT_TAG* p_ret;
2560 uint8_t tms;
2561 tNFC_STATUS status = NFC_STATUS_FAILED;
2562 bool b_blank_tag = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002563
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002564 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
2565 if (p_ret == NULL) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002566 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002567 "rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the "
2568 "tag!",
2569 p_t2t->tag_hdr[0]);
2570 return (NFC_STATUS_FAILED);
2571 }
2572
2573 if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0) {
2574 /* If OTP tag has valid NDEF Message, cannot format the tag */
2575 if ((p_t2t->ndef_msg_len > 0) && (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002576 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002577 "rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2578 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002579 }
2580
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002581 if (((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) &&
2582 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) ||
2583 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) &&
2584 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
2585 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
2586 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002587 LOG(WARNING) << StringPrintf(
2588 "rw_t2t_format_tag - Tag not blank to Format!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002589 return (NFC_STATUS_FAILED);
2590 } else {
2591 tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2592 b_blank_tag = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002593 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002594 } else
2595 tms = p_ret->tms;
2596
2597 memset(p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2598
2599 if (!b_blank_tag || !p_ret->b_multi_version) {
2600 status = rw_t2t_set_cc(tms);
2601 } else if (p_ret->version_block != 0) {
2602 /* If Version number is not read, READ it now */
2603 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2604
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002605 status = rw_t2t_read(p_ret->version_block);
2606 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002607 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002608 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002609 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2610 } else {
2611 /* UID block is the version block */
2612 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2613 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2614 rw_t2t_handle_format_tag_rsp(p_t2t->tag_hdr);
2615 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002616
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002617 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002618}
2619
2620/*******************************************************************************
2621**
2622** Function rw_t2t_soft_lock_tag
2623**
2624** Description This function will soft lock the tag after validating CC.
2625**
2626** Returns
2627** NFC_STATUS_OK, Command sent to soft lock the tag
2628** NFC_STATUS_FAILED: otherwise
2629**
2630*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002631tNFC_STATUS rw_t2t_soft_lock_tag(void) {
2632 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2633 tNFC_STATUS status = NFC_STATUS_FAILED;
2634 uint8_t write_block[T2T_BLOCK_SIZE];
2635 uint8_t num_locks;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002636
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002637 /* If CC block is read and cc3 is soft locked, reject the command */
2638 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002639 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002640 "rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: "
2641 "%u",
2642 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2643 return (NFC_STATUS_FAILED);
2644 }
2645
2646 if (p_t2t->b_hard_lock) {
2647 /* Should have performed NDEF Detection on dynamic memory structure tag,
2648 * before permanently converting to Read only
2649 * Even when no lock control tlv is present, default lock bytes should be
2650 * present */
2651
2652 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) &&
2653 (p_t2t->num_lockbytes == 0)) {
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: Lock TLV not detected! Cannot hard "
2656 "lock the tag");
2657 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002658 }
2659
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002660 /* On dynamic memory structure tag, reset all lock bytes status to 'Not
2661 * Updated' if not in Updated status */
2662 num_locks = 0;
2663 while (num_locks < p_t2t->num_lockbytes) {
2664 if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2665 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2666 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002667 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002668 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002669
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002670 memcpy(write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2671 write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002672
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002673 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2674 /* First Soft lock the tag */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002675 status = rw_t2t_write(T2T_CC_BLOCK, write_block);
2676 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002677 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
2678 p_t2t->b_read_hdr = false;
2679 } else {
2680 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2681 }
2682 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002683}
2684
2685/*****************************************************************************
2686**
2687** Function RW_T2tFormatNDef
2688**
2689** Description
2690** Format Tag content
2691**
2692** Returns
2693** NFC_STATUS_OK, Command sent to format Tag
2694** NFC_STATUS_FAILED: otherwise
2695**
2696*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002697tNFC_STATUS RW_T2tFormatNDef(void) {
2698 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2699 tNFC_STATUS status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002700
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002701 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002702 LOG(WARNING) << StringPrintf(
2703 "RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u",
2704 p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002705 return (NFC_STATUS_FAILED);
2706 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002707
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002708 if (!p_t2t->b_read_hdr) {
2709 /* If UID is not read, READ it now */
2710 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002711
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002712 status = rw_t2t_read(0);
2713 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002714 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002715 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002716 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2717 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002718 status = rw_t2t_format_tag();
2719 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002720 }
2721 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002722}
2723
2724/*******************************************************************************
2725**
2726** Function RW_T2tLocateTlv
2727**
2728** Description This function is used to perform TLV detection on a Type 2
2729** tag, and retrieve the tag's TLV attribute information.
2730**
2731** Before using this API, the application must call
2732** RW_SelectTagType to indicate that a Type 2 tag has been
2733** activated.
2734**
2735** Parameters: tlv_type : TLV to detect
2736**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002737** Returns NCI_STATUS_OK, if detection was started. Otherwise, error
2738** status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002739**
2740*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002741tNFC_STATUS RW_T2tLocateTlv(uint8_t tlv_type) {
2742 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2743 tNFC_STATUS status;
2744 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002745
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002746 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002747 LOG(ERROR) << StringPrintf(
2748 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002749 return (NFC_STATUS_BUSY);
2750 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002751
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002752 if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) &&
2753 (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002754 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2755 "RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002756 return (NFC_STATUS_FAILED);
2757 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002758
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002759 if ((tlv_type == TAG_LOCK_CTRL_TLV) && (p_t2t->b_read_hdr) &&
2760 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)) {
2761 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002762 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002763 "RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x",
2764 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2765 return (NFC_STATUS_FAILED);
2766 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002767
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002768 if ((tlv_type == TAG_NDEF_TLV) && (p_t2t->b_read_hdr) &&
2769 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) {
2770 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002771 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002772 "RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: "
2773 "0x%02x, CC[3]: 0x%02x",
2774 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
2775 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2776 return (NFC_STATUS_FAILED);
2777 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002778
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002779 p_t2t->work_offset = 0;
2780 p_t2t->tlv_detect = tlv_type;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002781
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002782 /* Reset control block variables based on type of tlv to detect */
2783 if (tlv_type == TAG_LOCK_CTRL_TLV) {
2784 p_t2t->num_lockbytes = 0;
2785 p_t2t->num_lock_tlvs = 0;
2786 } else if (tlv_type == TAG_MEM_CTRL_TLV) {
2787 p_t2t->num_mem_tlvs = 0;
2788 } else if (tlv_type == TAG_NDEF_TLV) {
2789 p_t2t->ndef_msg_offset = 0;
2790 p_t2t->num_lockbytes = 0;
2791 p_t2t->num_lock_tlvs = 0;
2792 p_t2t->num_mem_tlvs = 0;
2793 p_t2t->ndef_msg_len = 0;
2794 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
2795 } else {
2796 p_t2t->prop_msg_len = 0;
2797 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002798
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002799 if (!p_t2t->b_read_hdr) {
2800 /* First read CC block */
2801 block = 0;
2802 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2803 } else {
2804 /* Read first data block */
2805 block = T2T_FIRST_DATA_BLOCK;
2806 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2807 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002808
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002809 /* Start reading tag, looking for the specified TLV */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002810 status = rw_t2t_read((uint16_t)block);
2811 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002812 p_t2t->state = RW_T2T_STATE_DETECT_TLV;
2813 } else {
2814 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2815 }
2816 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002817}
2818
2819/*******************************************************************************
2820**
2821** Function RW_T2tDetectNDef
2822**
2823** Description This function is used to perform NDEF detection on a Type 2
2824** tag, and retrieve the tag's NDEF attribute information.
2825**
2826** Before using this API, the application must call
2827** RW_SelectTagType to indicate that a Type 2 tag has been
2828** activated.
2829**
2830** Parameters: none
2831**
2832** Returns NCI_STATUS_OK,if detect op started.Otherwise,error status.
2833**
2834*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002835tNFC_STATUS RW_T2tDetectNDef(bool skip_dyn_locks) {
2836 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Evan Chuc95c79c2013-04-12 17:38:09 -04002837
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002838 p_t2t->skip_dyn_locks = skip_dyn_locks;
Evan Chuc95c79c2013-04-12 17:38:09 -04002839
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002840 return RW_T2tLocateTlv(TAG_NDEF_TLV);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002841}
2842
2843/*******************************************************************************
2844**
2845** Function RW_T2tReadNDef
2846**
2847** Description Retrieve NDEF contents from a Type2 tag.
2848**
2849** The RW_T2T_NDEF_READ_EVT event is used to notify the
2850** application after reading the NDEF message.
2851**
2852** Before using this API, the RW_T2tDetectNDef function must
2853** be called to verify that the tag contains NDEF data, and to
2854** retrieve the NDEF attributes.
2855**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002856** Internally, this command will be separated into multiple
2857** Tag2 Read commands (if necessary) - depending on the NDEF
2858** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002859**
2860** Parameters: p_buffer: The buffer into which to read the NDEF message
2861** buf_len: The length of the buffer
2862**
2863** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
2864**
2865*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002866tNFC_STATUS RW_T2tReadNDef(uint8_t* p_buffer, uint16_t buf_len) {
2867 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2868 tNFC_STATUS status = NFC_STATUS_OK;
2869 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002870
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002871 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002872 LOG(ERROR) << StringPrintf(
2873 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002874 return (NFC_STATUS_FAILED);
2875 }
2876
2877 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002878 LOG(ERROR) << StringPrintf(
2879 "RW_T2tReadNDef - Error: NDEF detection not performed yet");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002880 return (NFC_STATUS_FAILED);
2881 }
2882
2883 if (buf_len < p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002884 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002885 "RW_T2tReadNDef - buffer size: %u less than NDEF msg sise: %u",
2886 buf_len, p_t2t->ndef_msg_len);
2887 return (NFC_STATUS_FAILED);
2888 }
2889
2890 if (!p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002891 LOG(WARNING) << StringPrintf(
2892 "RW_T2tReadNDef - NDEF Message length is zero");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002893 return (NFC_STATUS_NOT_INITIALIZED);
2894 }
2895
2896 p_t2t->p_ndef_buffer = p_buffer;
2897 p_t2t->work_offset = 0;
2898
2899 block = (uint16_t)(p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
2900 block -= block % T2T_READ_BLOCKS;
2901
2902 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2903
2904 if ((block == T2T_FIRST_DATA_BLOCK) && (p_t2t->b_read_data)) {
2905 p_t2t->state = RW_T2T_STATE_READ_NDEF;
2906 p_t2t->block_read = T2T_FIRST_DATA_BLOCK;
2907 rw_t2t_handle_ndef_read_rsp(p_t2t->tag_data);
2908 } else {
2909 /* Start reading NDEF Message */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002910 status = rw_t2t_read(block);
2911 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002912 p_t2t->state = RW_T2T_STATE_READ_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002913 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002914 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002915
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002916 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002917}
2918
2919/*******************************************************************************
2920**
2921** Function RW_T2tWriteNDef
2922**
2923** Description Write NDEF contents to a Type2 tag.
2924**
2925** Before using this API, the RW_T2tDetectNDef
2926** function must be called to verify that the tag contains
2927** NDEF data, and to retrieve the NDEF attributes.
2928**
2929** The RW_T2T_NDEF_WRITE_EVT callback event will be used to
2930** notify the application of the response.
2931**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002932** Internally, this command will be separated into multiple
2933** Tag2 Write commands (if necessary) - depending on the NDEF
2934** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002935**
2936** Parameters: msg_len: The length of the buffer
2937** p_msg: The NDEF message to write
2938**
2939** Returns NCI_STATUS_OK,if write was started. Otherwise, error status
2940**
2941*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002942tNFC_STATUS RW_T2tWriteNDef(uint16_t msg_len, uint8_t* p_msg) {
2943 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2944 uint16_t block;
2945 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002946
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002947 tNFC_STATUS status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002948
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002949 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002950 LOG(ERROR) << StringPrintf(
2951 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002952 return (NFC_STATUS_FAILED);
2953 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002954
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002955 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002956 LOG(ERROR) << StringPrintf(
2957 "RW_T2tWriteNDef - Error: NDEF detection not performed!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002958 return (NFC_STATUS_FAILED);
2959 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002960
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002961 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002962 LOG(ERROR) << StringPrintf(
2963 "RW_T2tWriteNDef - Write access not granted - CC3: %u",
2964 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002965 return (NFC_STATUS_REFUSED);
2966 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002967
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002968 /* Check if there is enough memory on the tag */
2969 if (msg_len > p_t2t->max_ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002970 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002971 "RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes",
2972 p_t2t->max_ndef_msg_len);
2973 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 OTP tag and tag has valid NDEF Message, stop writting new NDEF Message
2977 * as it may corrupt the tag */
2978 if ((p_t2t->ndef_msg_len > 0) &&
2979 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
2980 (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002981 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002982 "RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
2983 return (NFC_STATUS_FAILED);
2984 }
2985 p_t2t->p_new_ndef_buffer = p_msg;
2986 p_t2t->new_ndef_msg_len = msg_len;
2987 p_t2t->work_offset = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002988
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002989 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
2990 /* Read first NDEF Block before updating NDEF */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002991
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002992 block = (uint16_t)(p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002993
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002994 if ((block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) &&
2995 (p_t2t->b_read_data)) {
2996 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
2997 p_t2t->block_read = block;
2998 rw_t2t_handle_ndef_write_rsp(
2999 &p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
3000 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003001 status = rw_t2t_read(block);
3002 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003003 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003004 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003005 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3006 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003007
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003008 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003009}
3010
3011/*******************************************************************************
3012**
3013** Function RW_T2tSetTagReadOnly
3014**
3015** Description This function can be called to set T2 tag as read only.
3016**
3017** Parameters: b_hard_lock: To indicate hard lock the tag or not
3018**
3019** Returns NCI_STATUS_OK, if setting tag as read only was started.
3020** Otherwise, error status.
3021**
3022*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003023tNFC_STATUS RW_T2tSetTagReadOnly(bool b_hard_lock) {
3024 tNFC_STATUS status = NFC_STATUS_FAILED;
3025 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003026
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003027 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003028 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003029 "RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - "
3030 "State: %u",
3031 p_t2t->state);
3032 return (NFC_STATUS_FAILED);
3033 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003034
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003035 p_t2t->b_hard_lock = b_hard_lock;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003036
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003037 if (!p_t2t->b_read_hdr) {
3038 /* Read CC block before configuring tag as Read only */
3039 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003040 status = rw_t2t_read((uint16_t)0);
3041 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003042 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
3043 } else
3044 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3045 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003046 status = rw_t2t_soft_lock_tag();
3047 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003048 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003049
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003050 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003051}
3052
Ruchi Kandoi303fec12016-12-14 13:22:38 -08003053#endif /* (RW_NDEF_INCLUDED == TRUE) */