blob: 36c7fec66fe0082d3d262c210f25b3d7e32d37ea [file] [log] [blame]
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001/******************************************************************************
2 *
Evan Chue9629ba2014-01-31 11:18:47 -05003 * Copyright (C) 2010-2014 Broadcom Corporation
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * This file contains the implementation for Type 2 tag NDEF operation in
22 * Reader/Writer mode.
23 *
24 ******************************************************************************/
25#include <string.h>
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080026
27#include <android-base/stringprintf.h>
28#include <base/logging.h>
Ruchi Kandoi183352b2018-09-21 14:04:22 -070029#include <log/log.h>
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080030
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080031#include "nfc_target.h"
32
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080033#include "nci_hmsgs.h"
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080034#include "nfc_api.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080035#include "rw_api.h"
36#include "rw_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080037
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080038using android::base::StringPrintf;
39
40extern bool nfc_debug_enabled;
41
Ruchi Kandoi303fec12016-12-14 13:22:38 -080042#if (RW_NDEF_INCLUDED == TRUE)
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080043
44/* Local static functions */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080045static void rw_t2t_handle_cc_read_rsp(void);
46static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data);
47static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data);
48static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data);
49static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data);
50static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data);
51static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data);
52static uint8_t rw_t2t_get_tag_size(uint8_t* p_data);
53static void rw_t2t_extract_default_locks_info(void);
54static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
55 bool b_update_len);
56static uint8_t rw_t2t_get_ndef_flags(void);
57static uint16_t rw_t2t_get_ndef_max_size(void);
58static tNFC_STATUS rw_t2t_read_locks(void);
59static tNFC_STATUS rw_t2t_read_ndef_last_block(void);
60static void rw_t2t_update_attributes(void);
61static void rw_t2t_update_lock_attributes(void);
62static bool rw_t2t_is_lock_res_byte(uint16_t index);
63static bool rw_t2t_is_read_only_byte(uint16_t index);
64static tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len,
65 bool b_update_len);
66static tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block,
67 uint16_t msg_len,
68 bool b_update_len);
69static tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block);
70static tNFC_STATUS rw_t2t_add_terminator_tlv(void);
71static bool rw_t2t_is_read_before_write_block(uint16_t block,
72 uint16_t* p_block_to_read);
73static tNFC_STATUS rw_t2t_set_cc(uint8_t tms);
74static tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
75 uint16_t locked_area_size);
76static tNFC_STATUS rw_t2t_format_tag(void);
77static tNFC_STATUS rw_t2t_soft_lock_tag(void);
78static tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data);
79static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080080
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080081const uint8_t rw_t2t_mask_bits[8] = {0x01, 0x02, 0x04, 0x08,
82 0x10, 0x20, 0x40, 0x80};
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080083
84/*******************************************************************************
85**
86** Function rw_t2t_handle_rsp
87**
88** Description This function handles response to command sent during
89** NDEF and other tlv operation
90**
91** Returns None
92**
93*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080094void rw_t2t_handle_rsp(uint8_t* p_data) {
95 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080096
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080097 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
98 p_t2t->b_read_hdr = true;
99 memcpy(p_t2t->tag_hdr, p_data, T2T_READ_DATA_LEN);
100 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800101
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800102 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800103 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800104 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
105 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
106 rw_t2t_handle_cc_read_rsp();
107 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
108 rw_t2t_handle_lock_read_rsp(p_data);
109 } else {
110 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800111 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800112 } else if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
113 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
114 if (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] == T2T_CC0_NMN) {
115 rw_t2t_handle_cc_read_rsp();
116 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700117 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800118 "NDEF Detection failed!, CC[0]: 0x%02x, CC[1]: 0x%02x, CC[3]: "
119 "0x%02x",
120 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE],
121 p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
122 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
123 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
124 }
125 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS) {
126 rw_t2t_handle_lock_read_rsp(p_data);
127 } else {
128 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800129 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800130 } else {
131 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_CC) {
132 rw_t2t_handle_cc_read_rsp();
133 } else {
134 rw_t2t_handle_tlv_detect_rsp(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800135 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800136 }
137 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800138
139 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800140 rw_t2t_handle_config_tag_readonly(p_data);
141 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800142
143 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800144 rw_t2t_handle_format_tag_rsp(p_data);
145 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800146
147 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800148 rw_t2t_handle_ndef_read_rsp(p_data);
149 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800150
151 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800152 rw_t2t_handle_ndef_write_rsp(p_data);
153 break;
154 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800155}
156
157/*******************************************************************************
158**
159** Function rw_t2t_info_to_event
160**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800161** Description This function returns RW event code based on the current
162** state
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800163**
164** Returns RW event code
165**
166*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800167tRW_EVENT rw_t2t_info_to_event(const tT2T_CMD_RSP_INFO* p_info) {
168 tRW_EVENT rw_event;
169 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800170
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800171 switch (p_t2t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800172 case RW_T2T_STATE_DETECT_TLV:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800173 if (p_t2t->tlv_detect == TAG_NDEF_TLV)
174 rw_event = RW_T2T_NDEF_DETECT_EVT;
175 else
176 rw_event = RW_T2T_TLV_DETECT_EVT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800177
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800178 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800179
180 case RW_T2T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800181 rw_event = RW_T2T_NDEF_READ_EVT;
182 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800183
184 case RW_T2T_STATE_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800185 rw_event = RW_T2T_NDEF_WRITE_EVT;
186 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800187
188 case RW_T2T_STATE_SET_TAG_RO:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800189 rw_event = RW_T2T_SET_TAG_RO_EVT;
190 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800191
192 case RW_T2T_STATE_CHECK_PRESENCE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800193 rw_event = RW_T2T_PRESENCE_CHECK_EVT;
194 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800195
196 case RW_T2T_STATE_FORMAT_TAG:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800197 rw_event = RW_T2T_FORMAT_CPLT_EVT;
198 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800199
200 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800201 rw_event = t2t_info_to_evt(p_info);
202 break;
203 }
204 return rw_event;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800205}
206
207/*******************************************************************************
208**
209** Function rw_t2t_handle_cc_read_rsp
210**
211** Description Handle read cc bytes
212**
213** Returns none
214**
215*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800216static void rw_t2t_handle_cc_read_rsp(void) {
217 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800218
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800219 if (((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) &&
220 (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RO)) ||
221 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
222 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
223 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
224 /* Invalid Version number or RWA byte */
225 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
226 return;
227 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800228
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800229 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800230
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800231 if (rw_t2t_read((uint16_t)T2T_FIRST_DATA_BLOCK) != NFC_STATUS_OK) {
232 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
233 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800234}
235
236/*******************************************************************************
237**
238** Function rw_t2t_ntf_tlv_detect_complete
239**
240** Description Notify TLV detection complete to upper layer
241**
242** Returns none
243**
244*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800245static void rw_t2t_ntf_tlv_detect_complete(tNFC_STATUS status) {
246 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800247 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800248
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800249 if (p_t2t->tlv_detect == TAG_NDEF_TLV) {
250 /* Notify upper layer the result of NDEF detect op */
Ruchi Kandoi9ba6d242017-10-13 16:07:01 -0700251 tRW_DETECT_NDEF_DATA ndef_data = {};
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800252 ndef_data.status = status;
253 ndef_data.protocol = NFC_PROTOCOL_T2T;
254 ndef_data.flags = rw_t2t_get_ndef_flags();
255 ndef_data.cur_size = p_t2t->ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800256
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800257 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_FORMATED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800258
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800259 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] == T2T_CC3_RWA_RW)
260 ndef_data.max_size = (uint32_t)rw_t2t_get_ndef_max_size();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800261 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800262 ndef_data.max_size = ndef_data.cur_size;
263
264 if (ndef_data.max_size < ndef_data.cur_size) {
265 ndef_data.flags |= RW_NDEF_FL_READ_ONLY;
266 ndef_data.max_size = ndef_data.cur_size;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800267 }
268
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800269 if (!(ndef_data.flags & RW_NDEF_FL_READ_ONLY)) {
270 ndef_data.flags |= RW_NDEF_FL_SOFT_LOCKABLE;
271 if (status == NFC_STATUS_OK) ndef_data.flags |= RW_NDEF_FL_HARD_LOCKABLE;
272 }
273
274 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700275 tRW_DATA rw_data;
276 rw_data.ndef = ndef_data;
277 (*rw_cb.p_cback)(RW_T2T_NDEF_DETECT_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800278 } else if (p_t2t->tlv_detect == TAG_PROPRIETARY_TLV) {
Myles Watson1361d522017-09-26 13:39:54 -0700279 tRW_T2T_DETECT evt_data;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800280 evt_data.msg_len = p_t2t->prop_msg_len;
281 evt_data.status = status;
282 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700283 /* FIXME: Unsafe cast */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800284 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, (tRW_DATA*)&evt_data);
285 } else {
286 /* Notify upper layer the result of Lock/Mem TLV detect op */
Myles Watson1361d522017-09-26 13:39:54 -0700287 tRW_DETECT_TLV_DATA tlv_data;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800288 tlv_data.protocol = NFC_PROTOCOL_T2T;
289 if (p_t2t->tlv_detect == TAG_LOCK_CTRL_TLV) {
290 tlv_data.num_bytes = p_t2t->num_lockbytes;
291 } else {
292 tlv_data.num_bytes = 0;
293 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++) {
294 tlv_data.num_bytes += p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes;
295 }
296 }
297 tlv_data.status = status;
298 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -0700299 tRW_DATA rw_data;
300 rw_data.tlv = tlv_data;
301 (*rw_cb.p_cback)(RW_T2T_TLV_DETECT_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800302 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800303}
304
305/*******************************************************************************
306**
307** Function rw_t2t_handle_lock_read_rsp
308**
309** Description Handle response to reading lock bytes
310**
311** Returns none
312**
313*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800314static void rw_t2t_handle_lock_read_rsp(uint8_t* p_data) {
315 uint8_t updated_lock_byte;
316 uint8_t num_locks;
317 uint8_t offset = 0;
318 uint16_t lock_offset;
319 uint16_t base_lock_offset = 0;
320 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
321 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800322
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800323 /* Prepare NDEF/TLV attributes (based on current op) for sending response to
324 * upper layer */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800325
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800326 num_locks = 0;
327 updated_lock_byte = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800328
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800329 /* Extract all lock bytes present in the read 16 bytes
330 * but atleast one lock byte (base lock) should be present in the read 16
331 * bytes */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800332
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800333 while (num_locks < p_t2t->num_lockbytes) {
334 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
335 lock_offset =
336 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
337 p_t2t->lockbyte[num_locks].byte_index;
338 if (updated_lock_byte == 0) {
339 /* The offset of the first lock byte present in the 16 bytes read using
340 * READ command */
341 base_lock_offset = lock_offset;
342 /* Block number used to read may not be the block where lock offset is
343 * present */
344 offset = (uint8_t)(lock_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
345 /* Update the lock byte value in the control block */
346 p_t2t->lockbyte[num_locks].lock_byte = p_data[offset];
347 p_t2t->lockbyte[num_locks].b_lock_read = true;
348 updated_lock_byte++;
349 } else if (lock_offset > base_lock_offset) {
350 /* Atleast one lock byte will get updated in the control block */
351 if ((lock_offset - base_lock_offset + offset) < T2T_READ_DATA_LEN) {
352 /* And this lock byte is also present in the read data */
353 p_t2t->lockbyte[num_locks].lock_byte =
354 p_data[lock_offset - base_lock_offset + offset];
355 p_t2t->lockbyte[num_locks].b_lock_read = true;
356 updated_lock_byte++;
357 } else {
358 /* This lock byte is not present in the read data */
359 block = (uint16_t)(lock_offset / T2T_BLOCK_LEN);
360 block -= block % T2T_READ_BLOCKS;
361 /* send READ command to read this lock byte */
362 if (NFC_STATUS_OK != rw_t2t_read((uint16_t)block)) {
363 /* Unable to send Read command, notify failure status to upper layer
364 */
365 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
366 }
367 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800368 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800369 } else {
370 /* This Lock byte is not present in the read 16 bytes
371 * send READ command to read the lock byte */
372 if (NFC_STATUS_OK !=
373 rw_t2t_read((uint16_t)(lock_offset / T2T_BLOCK_LEN))) {
374 /* Unable to send Read command, notify failure status to upper layer
375 */
376 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
377 }
378 break;
379 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800380 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800381 num_locks++;
382 }
383 if (num_locks == p_t2t->num_lockbytes) {
384 /* All locks are read, notify upper layer */
385 rw_t2t_update_lock_attributes();
386 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_OK);
387 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800388}
389
390/*******************************************************************************
391**
392** Function rw_t2t_handle_tlv_detect_rsp
393**
394** Description Handle TLV detection.
395**
396** Returns none
397**
398*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800399static void rw_t2t_handle_tlv_detect_rsp(uint8_t* p_data) {
400 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
401 uint16_t offset;
402 uint16_t len = 0;
403 bool failed = false;
404 bool found = false;
405 tRW_EVENT event;
406 uint8_t index;
407 uint8_t count = 0;
408 uint8_t xx;
409 tNFC_STATUS status;
410 tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
411 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
412 uint8_t tlvtype = p_t2t->tlv_detect;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800413
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800414 if (p_t2t->work_offset == 0) {
415 /* Skip UID,Static Lock block,CC*/
416 p_t2t->work_offset = T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN;
417 p_t2t->b_read_data = true;
418 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
419 }
420
421 p_t2t->segment = 0;
422
423 for (offset = 0; offset < T2T_READ_DATA_LEN && !failed && !found;) {
424 if (rw_t2t_is_lock_res_byte((uint16_t)(p_t2t->work_offset + offset)) ==
425 true) {
426 /* Skip locks, reserved bytes while searching for TLV */
427 offset++;
428 continue;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800429 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800430 switch (p_t2t->substate) {
431 case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
432 /* Search for the tlv */
433 p_t2t->found_tlv = p_data[offset++];
434 switch (p_t2t->found_tlv) {
435 case TAG_NULL_TLV: /* May be used for padding. SHALL ignore this */
436 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800437
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800438 case TAG_NDEF_TLV:
439 if (tlvtype == TAG_NDEF_TLV) {
440 /* NDEF Detected, now collect NDEF Attributes including NDEF
441 * Length */
442 index = (offset % T2T_BLOCK_SIZE);
443 /* Backup ndef first block */
444 memcpy(p_t2t->ndef_first_block, &p_data[offset - index], index);
445 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
446 } else if (tlvtype == TAG_PROPRIETARY_TLV) {
447 /* Proprietary TLV can exist after NDEF Tlv so we continue
448 * searching */
449 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
450 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
451 (p_t2t->num_lockbytes > 0)) ||
452 ((tlvtype == TAG_MEM_CTRL_TLV) &&
453 (p_t2t->num_mem_tlvs > 0))) {
454 /* Lock / Memory control tlv cannot exist after NDEF TLV
455 * So when NDEF is found, we stop searching for Lock and Memory
456 * control tlv */
457 found = true;
458 } else {
459 /* While searching for Lock / Memory control tlv, if NDEF TLV is
460 * found
461 * first then our search for Lock /Memory control tlv failed and
462 * we stop here */
463 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800464 }
465 break;
466
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800467 case TAG_LOCK_CTRL_TLV:
468 case TAG_MEM_CTRL_TLV:
469 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
470 break;
471
472 case TAG_PROPRIETARY_TLV:
473 if (tlvtype == TAG_PROPRIETARY_TLV) {
474 index = (offset % T2T_BLOCK_SIZE);
475 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
476 } else {
477 /* NDEF/LOCK/MEM TLV can exist after Proprietary Tlv so we
478 * continue searching, skiping proprietary tlv */
479 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN;
480 }
481 break;
482
483 case TAG_TERMINATOR_TLV: /* Last TLV block in the data area. Must be
484 no NDEF nessage */
485 if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
486 (p_t2t->num_lockbytes > 0)) ||
487 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
488 /* No more Lock/Memory TLV control tlv in the tag, so stop
489 * searching */
490 found = true;
491 } else {
492 /* NDEF/Lock/Memory/Proprietary TLV cannot exist after Terminator
493 * Tlv */
494 failed = true;
495 }
496 break;
497 default:
498 failed = true;
499 }
500 break;
501
502 case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
503 len = p_data[offset];
504 switch (p_t2t->found_tlv) {
505 case TAG_NDEF_TLV:
506 p_t2t->ndef_header_offset = offset + p_t2t->work_offset;
507 if (len == TAG_LONG_NDEF_LEN_FIELD_BYTE0) {
508 /* The next two bytes constitute length bytes */
509 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
510 } else {
511 /* one byte length field */
512 p_t2t->ndef_msg_len = len;
513 p_t2t->bytes_count = p_t2t->ndef_msg_len;
514 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
515 }
516 break;
517
518 case TAG_PROPRIETARY_TLV:
519 if (len == T2T_LONG_NDEF_LEN_FIELD_BYTE0) {
520 /* The next two bytes constitute length bytes */
521 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0;
522 } else {
523 /* one byte length field */
524 p_t2t->prop_msg_len = len;
525 p_t2t->bytes_count = p_t2t->prop_msg_len;
526 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
527 }
528 break;
529 }
530 offset++;
531 break;
532
533 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
534 switch (p_t2t->found_tlv) {
535 case TAG_LOCK_CTRL_TLV:
536 case TAG_MEM_CTRL_TLV:
537
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800538 len = p_data[offset];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800539 if (len == TAG_DEFAULT_TLV_LEN) {
540 /* Valid Lock control TLV */
541 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
542 p_t2t->bytes_count = TAG_DEFAULT_TLV_LEN;
543 } else if (((tlvtype == TAG_LOCK_CTRL_TLV) &&
544 (p_t2t->num_lockbytes > 0)) ||
545 ((tlvtype == TAG_MEM_CTRL_TLV) &&
546 (p_t2t->num_mem_tlvs > 0))) {
547 /* Stop searching for Lock/ Memory control tlv */
548 found = true;
549 } else {
550 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800551 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800552 break;
553
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800554 case TAG_NDEF_TLV:
555 case TAG_PROPRIETARY_TLV:
556 /* The first length byte */
557 p_t2t->bytes_count = (uint8_t)p_data[offset];
558 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800559 break;
560 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800561 offset++;
562 break;
563
564 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
565 /* Prepare NDEF Message length */
566 p_t2t->bytes_count = (p_t2t->bytes_count << 8) + p_data[offset];
567 if (p_t2t->found_tlv == TAG_NDEF_TLV) {
568 p_t2t->ndef_msg_len = p_t2t->bytes_count;
569 } else if (p_t2t->found_tlv == TAG_PROPRIETARY_TLV) {
570 p_t2t->prop_msg_len = p_t2t->bytes_count;
571 }
572 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
573 offset++;
574 break;
575
576 case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
577 switch (p_t2t->found_tlv) {
578 case TAG_NDEF_TLV:
579 if ((p_t2t->bytes_count == p_t2t->ndef_msg_len) &&
580 (tlvtype == TAG_NDEF_TLV)) {
581 /* The first byte offset after length field */
582 p_t2t->ndef_msg_offset = offset + p_t2t->work_offset;
583 }
584 /* Reduce number of NDEF bytes remaining to pass over NDEF TLV */
585 if (p_t2t->bytes_count > 0) p_t2t->bytes_count--;
586
587 if (tlvtype == TAG_NDEF_TLV) {
588 found = true;
589 p_t2t->ndef_status = T2T_NDEF_DETECTED;
590 } else if (p_t2t->bytes_count == 0) {
591 /* Next byte could be a different TLV */
592 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
593 }
594 break;
595
596 case TAG_LOCK_CTRL_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800597 if (p_t2t->bytes_count > 0) {
598 p_t2t->bytes_count--;
599 } else {
600 LOG(ERROR) << StringPrintf("Underflow p_t2t->bytes_count!");
601 android_errorWriteLog(0x534e4554, "120506143");
602 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800603 if ((tlvtype == TAG_LOCK_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
Alisher Alikhodjaev6ddbd262020-01-16 14:01:15 -0800604 if (p_t2t->num_lockbytes > 0) {
605 LOG(ERROR) << StringPrintf("Malformed tag!");
606 android_errorWriteLog(0x534e4554, "147309942");
607 failed = true;
608 break;
609 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800610 /* Collect Lock TLV */
611 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
612 if (p_t2t->bytes_count == 0) {
613 /* Lock TLV is collected and buffered in tlv_value, now decode
614 * it */
615 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
616 (p_t2t->tlv_value[0] >> 4) & 0x0F;
617 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset *=
618 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
619 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset +=
620 p_t2t->tlv_value[0] & 0x0F;
621 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
622 (uint8_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
Alisher Alikhodjaeva639b702020-01-29 20:34:26 -0800623 /* Note: 0 value in DLA_NbrLockBits means 256 */
624 count = p_t2t->tlv_value[1];
625 /* Set it to max value that can be stored in lockbytes */
626 if (count == 0) {
627#if RW_T2T_MAX_LOCK_BYTES > 0x1F
628 count = UCHAR_MAX;
629#else
630 count = RW_T2T_MAX_LOCK_BYTES * TAG_BITS_PER_BYTE;
631#endif
632 }
633 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits = count;
634 count = count / TAG_BITS_PER_BYTE +
635 ((count % TAG_BITS_PER_BYTE != 0) ? 1 : 0);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800636
637 /* Extract lockbytes info addressed by this Lock TLV */
638 xx = 0;
Ruchi Kandoi183352b2018-09-21 14:04:22 -0700639 if (count > RW_T2T_MAX_LOCK_BYTES) {
640 count = RW_T2T_MAX_LOCK_BYTES;
641 android_errorWriteLog(0x534e4554, "112161557");
642 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800643 while (xx < count) {
644 p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index =
645 p_t2t->num_lock_tlvs;
646 p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index = xx;
647 p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read = false;
648 xx++;
649 p_t2t->num_lockbytes++;
650 }
651 p_t2t->num_lock_tlvs++;
652 rw_t2t_update_attributes();
653 /* Next byte could be a different TLV */
654 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
655 }
656 } else {
657 /* If not looking for lock/ndef tlv, just skip this Lock TLV */
658 if (p_t2t->bytes_count == 0) {
659 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
660 }
661 }
662 break;
663
664 case TAG_MEM_CTRL_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800665 if (p_t2t->bytes_count > 0) {
666 p_t2t->bytes_count--;
667 } else {
668 LOG(ERROR) << StringPrintf("bytes_count underflow!");
669 android_errorWriteLog(0x534e4554, "120506143");
670 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800671 if ((tlvtype == TAG_MEM_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
672 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
673 if (p_t2t->bytes_count == 0) {
674 if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700675 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800676 "rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated "
677 "for Memory tlv has reached");
678 failed = true;
679 } else {
680 /* Extract memory control tlv */
681 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
682 (p_t2t->tlv_value[0] >> 4) & 0x0F;
683 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
684 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
685 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
686 p_t2t->tlv_value[0] & 0x0F;
687 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
688 p_t2t->tlv_value[1];
689 p_t2t->num_mem_tlvs++;
690 rw_t2t_update_attributes();
691 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
692 }
693 }
694 } else {
695 if (p_t2t->bytes_count == 0) {
696 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
697 }
698 }
699 break;
700
701 case TAG_PROPRIETARY_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800702 if (p_t2t->bytes_count > 0) {
703 p_t2t->bytes_count--;
704 } else {
705 LOG(ERROR) << StringPrintf("bytes_count underflow!");
706 android_errorWriteLog(0x534e4554, "120506143");
707 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800708 if (tlvtype == TAG_PROPRIETARY_TLV) {
709 found = true;
710 p_t2t->prop_msg_len = len;
711 } else {
712 if (p_t2t->bytes_count == 0) {
713 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
714 }
715 }
716 break;
717 }
718 offset++;
719 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800720 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800721 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800722
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800723 p_t2t->work_offset += T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800724
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800725 event = rw_t2t_info_to_event(p_cmd_rsp_info);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800726
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800727 /* If not found and not failed, read next block and search tlv */
728 if (!found && !failed) {
729 if (p_t2t->work_offset >=
730 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR)) {
731 if (((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0)) ||
732 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
733 found = true;
734 } else {
735 failed = true;
736 }
737 } else {
738 if (rw_t2t_read((uint16_t)((p_t2t->work_offset / T2T_BLOCK_LEN) +
739 T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
740 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800741 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800742 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800743
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800744 if (failed || found) {
745 if (tlvtype == TAG_LOCK_CTRL_TLV) {
746 /* Incase no Lock control tlv is present then look for default dynamic
747 * lock bytes */
748 rw_t2t_extract_default_locks_info();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800749
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800750 /* Send command to read the dynamic lock bytes */
751 status = rw_t2t_read_locks();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800752
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800753 if (status != NFC_STATUS_CONTINUE) {
754 /* If unable to read a lock/all locks read, notify upper layer */
755 rw_t2t_update_lock_attributes();
756 rw_t2t_ntf_tlv_detect_complete(status);
757 }
758 } else if (tlvtype == TAG_NDEF_TLV) {
759 rw_t2t_extract_default_locks_info();
760
761 if (failed) {
762 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
763 } else {
764 /* NDEF present,Send command to read the dynamic lock bytes */
765 status = rw_t2t_read_locks();
766 if (status != NFC_STATUS_CONTINUE) {
767 /* If unable to read a lock/all locks read, notify upper layer */
768 rw_t2t_update_lock_attributes();
769 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800770 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800771 }
772 } else {
773 /* Notify Memory/ Proprietary tlv detect result */
774 status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
775 rw_t2t_ntf_tlv_detect_complete(status);
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}
779
780/*******************************************************************************
781**
782** Function rw_t2t_read_locks
783**
784** Description This function will send command to read next unread locks
785**
786** Returns NFC_STATUS_OK, if all locks are read successfully
787** NFC_STATUS_FAILED, if reading locks failed
788** NFC_STATUS_CONTINUE, if reading locks is in progress
789**
790*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800791tNFC_STATUS rw_t2t_read_locks(void) {
792 uint8_t num_locks = 0;
793 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
794 tNFC_STATUS status = NFC_STATUS_CONTINUE;
795 uint16_t offset;
796 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800797
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800798 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) ||
799 (p_t2t->skip_dyn_locks)) {
800 /* Skip reading dynamic lock bytes if CC is set as Read only or layer above
801 * instructs to skip */
802 while (num_locks < p_t2t->num_lockbytes) {
803 p_t2t->lockbyte[num_locks].lock_byte = 0x00;
804 p_t2t->lockbyte[num_locks].b_lock_read = true;
805 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800806 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800807 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800808
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800809 while (num_locks < p_t2t->num_lockbytes) {
810 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
811 /* Send Read command to read the first un read locks */
812 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
813 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800814
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800815 /* Read 16 bytes where this lock byte is present */
816 block = (uint16_t)(offset / T2T_BLOCK_LEN);
817 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800818
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800819 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
820 /* send READ8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800821 status = rw_t2t_read((uint16_t)block);
822 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800823 /* Reading Locks */
824 status = NFC_STATUS_CONTINUE;
825 } else {
826 status = NFC_STATUS_FAILED;
827 }
828 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800829 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800830 num_locks++;
831 }
832 if (num_locks == p_t2t->num_lockbytes) {
833 /* All locks are read */
834 status = NFC_STATUS_OK;
835 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800836
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800837 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800838}
839
840/*******************************************************************************
841**
842** Function rw_t2t_extract_default_locks_info
843**
844** Description This function will prepare lockbytes information for default
845** locks present in the tag in the absence of lock control tlv.
846** Adding a virtual lock control tlv for these lock bytes for
847** easier manipulation.
848**
849** Returns None
850**
851*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800852void rw_t2t_extract_default_locks_info(void) {
853 uint8_t num_dynamic_lock_bits;
854 uint8_t num_dynamic_lock_bytes;
855 uint8_t xx;
856 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
857 const tT2T_INIT_TAG* p_ret;
858 uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800859
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800860 if ((p_t2t->num_lock_tlvs == 0) &&
861 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
862 /* No Lock control tlv is detected. Indicates lock bytes are present in
863 * default location */
864 /* Add a virtual Lock tlv to map this default lock location */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800865 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
866 if (p_ret != NULL) bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800867
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800868 num_dynamic_lock_bits =
869 ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
870 (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
871 bytes_locked_per_lock_bit;
872 num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
873 num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
Alisher Alikhodjaeva639b702020-01-29 20:34:26 -0800874 if (num_dynamic_lock_bytes > RW_T2T_MAX_LOCK_BYTES) {
875 LOG(ERROR) << StringPrintf(
876 "rw_t2t_extract_default_locks_info - buffer size: %u less than "
877 "DynLock area sise: %u",
878 RW_T2T_MAX_LOCK_BYTES, num_dynamic_lock_bytes);
879 num_dynamic_lock_bytes = RW_T2T_MAX_LOCK_BYTES;
880 android_errorWriteLog(0x534e4554, "147310721");
881 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800882
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800883 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
884 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
885 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
886 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
887 bytes_locked_per_lock_bit;
888 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 -0800889
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800890 /* Based on tag data size the number of locks present in the default
891 * location changes */
892 for (xx = 0; xx < num_dynamic_lock_bytes; xx++) {
893 p_t2t->lockbyte[xx].tlv_index = p_t2t->num_lock_tlvs;
894 p_t2t->lockbyte[xx].byte_index = xx;
895 p_t2t->lockbyte[xx].b_lock_read = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800896 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800897 p_t2t->num_lockbytes = num_dynamic_lock_bytes;
898 p_t2t->num_lock_tlvs = 1;
899 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800900}
901
902/*******************************************************************************
903**
904** Function rw_t2t_read_ndef_last_block
905**
906** Description This function will locate and read the last ndef block.
907** The last ndef block refers to the tag block where last byte
908** of new ndef message will reside. Also this function will
909** locate the offset of Terminator TLV based on the size of
910** new NDEF Message
911**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800912** Returns NCI_STATUS_OK, if able to locate last ndef block & read
913** started. Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800914**
915*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800916tNFC_STATUS rw_t2t_read_ndef_last_block(void) {
917 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
918 uint16_t header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN)
919 ? T2T_LONG_NDEF_LEN_FIELD_LEN
920 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
921 uint16_t num_ndef_bytes;
922 uint16_t total_ndef_bytes;
923 uint16_t last_ndef_byte_offset;
924 uint16_t terminator_tlv_byte_index;
925 tNFC_STATUS status;
926 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800927
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800928 total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
929 num_ndef_bytes = 0;
930 last_ndef_byte_offset = p_t2t->ndef_header_offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800931
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800932 /* Locate NDEF final block based on the size of new NDEF Message */
933 while (num_ndef_bytes < total_ndef_bytes) {
934 if (rw_t2t_is_lock_res_byte((uint16_t)(last_ndef_byte_offset)) == false)
935 num_ndef_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800936
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800937 last_ndef_byte_offset++;
938 }
939 p_t2t->ndef_last_block_num =
940 (uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
941 block = p_t2t->ndef_last_block_num;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800942
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800943 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
944 /* Read NDEF last block before updating */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800945 status = rw_t2t_read(block);
946 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800947 if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
948 /* Locate Terminator TLV Block */
949 total_ndef_bytes++;
950 terminator_tlv_byte_index = last_ndef_byte_offset;
951
952 while (num_ndef_bytes < total_ndef_bytes) {
953 if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
954 false)
955 num_ndef_bytes++;
956
957 terminator_tlv_byte_index++;
958 }
959
960 p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
961 } else {
962 /* No space for Terminator TLV */
963 p_t2t->terminator_byte_index = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800964 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800965 }
966 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800967}
968
969/*******************************************************************************
970**
971** Function rw_t2t_read_terminator_tlv_block
972**
973** Description This function will read the block where terminator tlv will
974** be added later
975**
976** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
977**
978*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800979tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
980 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
981 tNFC_STATUS status;
982 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800983
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800984 /* Send read command to read base block (Block % 4==0) where this block is
985 * also read as part of 16 bytes */
986 block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
987 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800988
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800989 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
990 /* Read the block where Terminator TLV may be added later during NDEF Write
991 * operation */
992 status = rw_t2t_read(block);
993 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800994}
995
996/*******************************************************************************
997**
998** Function rw_t2t_read_ndef_next_block
999**
1000** Description This function will read the tag block passed as argument
1001**
1002** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
1003**
1004*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001005tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block) {
1006 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1007 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001008
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001009 /* Send read command to read base block (Block % 4==0) where this block is
1010 * also read as part of 16 bytes */
1011 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001012
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001013 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
1014 /* Read the block */
1015 status = rw_t2t_read(block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001016
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001017 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001018}
1019
1020/*******************************************************************************
1021**
1022** Function rw_t2t_is_read_before_write_block
1023**
1024** Description This function will check if the block has to be read before
1025** writting to avoid over writting in to lock/reserved bytes
1026** present in the block.
1027** If no bytes in the block can be overwritten it moves in to
1028** next block and check. Finally it finds a block where part of
1029** ndef bytes can exist and check if the whole block can be
1030** updated or only part of block can be modified.
1031**
1032** Returns TRUE, if the block returned should be read before writting
1033** FALSE, if the block need not be read as it was already
1034** read or during NDEF write we may completely overwrite
1035** the block and there is no reserved or locked bytes in
1036** that block
1037**
1038*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001039static bool rw_t2t_is_read_before_write_block(uint16_t block,
1040 uint16_t* p_block_to_read) {
1041 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1042 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1043 uint8_t count;
1044 uint8_t index;
1045 uint16_t tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1046 bool read_before_write = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001047
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001048 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1049 /* First NDEF block is already read */
1050 read_before_write = false;
1051 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
1052 } else if (block == p_t2t->ndef_last_block_num) {
1053 /* Last NDEF block is already read */
1054 read_before_write = false;
1055 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1056 } else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) {
1057 /* Terminator tlv block is already read */
1058 read_before_write = false;
1059 memcpy(p_t2t->ndef_read_block, p_t2t->terminator_tlv_block, T2T_BLOCK_SIZE);
1060 } else {
1061 count = 0;
1062 while (block < tag_size) {
1063 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001064
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001065 while (index < T2T_BLOCK_SIZE) {
1066 /* check if it is a reserved or locked byte */
1067 if (rw_t2t_is_lock_res_byte(
1068 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1069 count++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001070 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001071 index++;
1072 }
1073 if (count == T2T_BLOCK_SIZE) {
1074 /* All the bytes in the block are free to NDEF write */
1075 read_before_write = false;
1076 break;
1077 } else if (count == 0) {
1078 /* The complete block is not free for NDEF write */
1079 index = 0;
1080 block++;
1081 } else {
1082 /* The block has reseved byte (s) or locked byte (s) or both */
1083 read_before_write = true;
1084 break;
1085 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001086 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001087 }
1088 /* Return the block to read next before NDEF write */
1089 *p_block_to_read = block;
1090 return read_before_write;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001091}
1092
1093/*******************************************************************************
1094**
1095** Function rw_t2t_write_ndef_first_block
1096**
1097** Description This function will write the first NDEF block with Length
1098** field reset to zero.
1099** Also after writting NDEF this function may be called to
1100** update new NDEF length
1101**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001102** Returns NCI_STATUS_OK, if write was started.
1103** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001104**
1105*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001106tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len, bool b_update_len) {
1107 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1108 uint8_t new_lengthfield_len;
1109 uint8_t write_block[4];
1110 uint8_t block;
1111 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1112 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1113 tNFC_STATUS status;
1114 uint8_t length_field[3];
1115 uint8_t index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001116
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001117 p_t2t->work_offset = 0;
1118 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1119 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1120 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1121 if (new_lengthfield_len == 3) {
1122 /* New NDEF is Long NDEF */
1123 if (msg_len == 0) {
1124 /* Clear NDEF length field */
1125 length_field[0] = 0x00;
1126 length_field[1] = 0x00;
1127 length_field[2] = 0x00;
1128 } else {
1129 /* Update NDEF length field with new NDEF Msg len */
1130 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1131 length_field[1] = (uint8_t)(msg_len >> 8);
1132 length_field[2] = (uint8_t)(msg_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001133 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001134 } else {
1135 /* New NDEF is Short NDEF */
1136 length_field[0] = (uint8_t)(msg_len);
1137 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001138
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001139 /* updating ndef_first_block with new ndef message */
1140 memcpy(write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001141
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001142 index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1143 block = (uint8_t)(p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001144
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001145 while (p_t2t->work_offset == 0 && block < total_blocks) {
1146 /* update length field */
1147 while (index < T2T_BLOCK_SIZE &&
1148 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1149 if (rw_t2t_is_lock_res_byte(
1150 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1151 write_block[index] = length_field[p_t2t->work_offset];
1152 p_t2t->work_offset++;
1153 }
1154 index++;
1155 if (p_t2t->work_offset == new_lengthfield_len) {
1156 break;
1157 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001158 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001159 /* If more space in this block then add ndef message */
1160 while (index < T2T_BLOCK_SIZE &&
1161 p_t2t->work_offset <
1162 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1163 if (rw_t2t_is_lock_res_byte(
1164 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1165 write_block[index] =
1166 p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1167 p_t2t->work_offset++;
1168 }
1169 index++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001170 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001171 if (p_t2t->work_offset == 0) {
1172 /* If no bytes are written move to next block */
1173 index = 0;
1174 block++;
1175 if (block == p_t2t->ndef_last_block_num) {
1176 memcpy(write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1177 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001178 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001179 }
1180 if (p_t2t->work_offset == 0) {
1181 status = NFC_STATUS_FAILED;
1182 } else {
1183 rw_t2t_update_cb(block, write_block, b_update_len);
1184 /* Update the identified block with newly prepared data */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001185 status = rw_t2t_write(block, write_block);
1186 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001187 p_t2t->b_read_data = false;
1188 }
1189 }
1190 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001191}
1192
1193/*******************************************************************************
1194**
1195** Function rw_t2t_write_ndef_next_block
1196**
1197** Description This function can be called to write an NDEF message block
1198**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001199** Returns NCI_STATUS_OK, if write was started.
1200** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001201**
1202*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001203tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block, uint16_t msg_len,
1204 bool b_update_len) {
1205 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1206 uint8_t new_lengthfield_len;
1207 uint8_t write_block[4];
1208 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1209 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1210 uint16_t initial_offset;
1211 uint8_t length_field[3];
1212 uint8_t index;
1213 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001214
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001215 /* Write NDEF Message */
1216 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1217 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1218 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001219
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001220 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001221
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001222 memcpy(write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001223
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001224 if (p_t2t->work_offset >= new_lengthfield_len) {
1225 /* Length field is updated, write ndef message field */
1226 initial_offset = p_t2t->work_offset;
1227 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1228 while (index < T2T_BLOCK_SIZE &&
1229 p_t2t->work_offset <
1230 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1231 if (rw_t2t_is_lock_res_byte(
1232 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1233 write_block[index] =
1234 p_t2t
1235 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1236 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001237 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001238 index++;
1239 }
1240 if (p_t2t->work_offset == initial_offset) {
1241 index = 0;
1242 block++;
1243 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001244 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001245 } else {
1246 /* Complete writting Length field and then write ndef message */
1247 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1248 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1249 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1250 if (new_lengthfield_len == 3) {
1251 /* New NDEF is Long NDEF */
1252 if (msg_len == 0) {
1253 length_field[0] = 0x00;
1254 length_field[1] = 0x00;
1255 length_field[2] = 0x00;
1256 } else {
1257 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1258 length_field[1] = (uint8_t)(msg_len >> 8);
1259 length_field[2] = (uint8_t)(msg_len);
1260 }
1261 } else {
1262 /* New NDEF is short NDEF */
1263 length_field[0] = (uint8_t)(msg_len);
1264 }
1265 initial_offset = p_t2t->work_offset;
1266 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1267 /* Update length field */
1268 while (index < T2T_BLOCK_SIZE &&
1269 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1270 if (rw_t2t_is_lock_res_byte(
1271 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1272 write_block[index] = length_field[p_t2t->work_offset];
1273 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001274 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001275 index++;
1276 if (p_t2t->work_offset == new_lengthfield_len) {
1277 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001278 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001279 }
1280 /* Update ndef message field */
1281 while (index < T2T_BLOCK_SIZE &&
1282 p_t2t->work_offset <
1283 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1284 if (rw_t2t_is_lock_res_byte(
1285 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1286 write_block[index] =
1287 p_t2t
1288 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1289 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001290 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001291 index++;
1292 }
1293 if (p_t2t->work_offset == initial_offset) {
1294 index = 0;
1295 block++;
1296 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001297 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001298 }
1299 if (p_t2t->work_offset == initial_offset) {
1300 status = NFC_STATUS_FAILED;
1301 } else {
1302 rw_t2t_update_cb(block, write_block, b_update_len);
1303 /* Write the NDEF Block */
1304 status = rw_t2t_write(block, write_block);
1305 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001306
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001307 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001308}
1309
1310/*******************************************************************************
1311**
1312** Function rw_t2t_update_cb
1313**
1314** Description This function can be called to write an NDEF message block
1315**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001316** Returns NCI_STATUS_OK, if write was started.
1317** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001318**
1319*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001320static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
1321 bool b_update_len) {
1322 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1323 uint8_t new_lengthfield_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001324
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001325 /* Write NDEF Message */
1326 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1327 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1328 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001329
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001330 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1331 /* Update ndef first block if the 'block' points to ndef first block */
1332 memcpy(p_t2t->ndef_first_block, p_write_block, T2T_BLOCK_SIZE);
1333 }
1334 if (p_t2t->terminator_byte_index / T2T_BLOCK_SIZE == block) {
1335 /* Update terminator block if the 'block' points to terminator tlv block */
1336 memcpy(p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1337 }
1338 if (b_update_len == false) {
1339 if (block == p_t2t->ndef_last_block_num) {
1340 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1341 p_t2t->work_offset = 0;
1342 /* Update ndef final block if the 'block' points to ndef final block */
1343 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
1344 } else {
1345 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001346 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001347 } else {
1348 if (block == p_t2t->ndef_last_block_num) {
1349 /* Update the backup of Ndef final block TLV block */
1350 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001351 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001352
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001353 if (p_t2t->work_offset >= new_lengthfield_len) {
1354 if (p_t2t->terminator_byte_index != 0) {
1355 /* Add Terminator TLV as part of NDEF Write operation */
1356 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1357 } else {
1358 /* Skip adding Terminator TLV */
1359 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1360 }
1361 } else {
1362 /* Part of NDEF Message Len should be added in the next block */
1363 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001364 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001365 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001366}
1367
1368/*******************************************************************************
1369**
1370** Function rw_t2t_get_ndef_flags
1371**
1372** Description Prepare NDEF Flags
1373**
1374** Returns NDEF Flag value
1375**
1376*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001377static uint8_t rw_t2t_get_ndef_flags(void) {
1378 uint8_t flags = 0;
1379 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1380 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001381
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001382 flags |= RW_NDEF_FL_SUPPORTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001383
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001384 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) ||
1385 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1386 flags |= RW_NDEF_FL_FORMATABLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001387
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001388 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1389 flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001390
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001391 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1392 (p_ret->b_otp)) {
1393 /* Set otp flag */
1394 flags |= RW_NDEF_FL_OTP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001395
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001396 /* Set Read only flag if otp tag already has NDEF Message */
1397 if (p_t2t->ndef_msg_len) flags |= RW_NDEF_FL_READ_ONLY;
1398 }
1399 return flags;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001400}
1401
1402/*******************************************************************************
1403**
1404** Function rw_t2t_get_ndef_max_size
1405**
1406** Description Calculate maximum size of NDEF message that can be written
1407** on to the tag
1408**
1409** Returns Maximum size of NDEF Message
1410**
1411*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001412static uint16_t rw_t2t_get_ndef_max_size(void) {
1413 uint16_t offset;
1414 uint8_t xx;
1415 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1416 uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
1417 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
1418 p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001419
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001420 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1421 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001422
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001423 offset = p_t2t->ndef_msg_offset;
1424 p_t2t->max_ndef_msg_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001425
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001426 if ((tag_size < T2T_STATIC_SIZE) ||
1427 (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
1428 ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
1429 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
1430 /* Tag not formated, assume static tag */
1431 p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
1432 T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001433 return p_t2t->max_ndef_msg_len;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001434 }
1435
1436 /* Starting from NDEF Message offset find the first locked data byte */
1437 while (offset < tag_size) {
1438 if (rw_t2t_is_lock_res_byte((uint16_t)offset) == false) {
1439 if (rw_t2t_is_read_only_byte((uint16_t)offset) == true) break;
1440 p_t2t->max_ndef_msg_len++;
1441 }
1442 offset++;
1443 }
1444 /* NDEF Length field length changes based on NDEF size */
1445 if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
1446 ((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
1447 T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
1448 p_t2t->max_ndef_msg_len -=
1449 (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1450 ? 1
1451 : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1452 }
1453 return p_t2t->max_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001454}
1455
1456/*******************************************************************************
1457**
1458** Function rw_t2t_add_terminator_tlv
1459**
1460** Description This function will add terminator TLV after NDEF Message
1461**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001462** Returns NCI_STATUS_OK, if write was started.
1463** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001464**
1465*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001466tNFC_STATUS rw_t2t_add_terminator_tlv(void) {
1467 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1468 tNFC_STATUS status;
1469 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001470
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001471 /* Add Terminator TLV after NDEF Message */
1472 p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
1473 TAG_TERMINATOR_TLV;
1474 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001475
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001476 block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
1477 status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001478
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001479 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001480}
1481
1482/*******************************************************************************
1483**
1484** Function rw_t2t_handle_ndef_read_rsp
1485**
1486** Description This function handles reading an NDEF message.
1487**
1488** Returns none
1489**
1490*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001491static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data) {
1492 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1493 tRW_READ_DATA evt_data;
1494 uint16_t len;
1495 uint16_t offset;
1496 bool failed = false;
1497 bool done = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001498
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001499 /* On the first read, adjust for any partial block offset */
1500 offset = 0;
1501 len = T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001502
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001503 if (p_t2t->work_offset == 0) {
1504 /* The Ndef Message offset may be present in the read 16 bytes */
1505 offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1506 }
1507
1508 /* Skip all reserved and lock bytes */
1509 while ((offset < len) && (p_t2t->work_offset < p_t2t->ndef_msg_len))
1510
1511 {
1512 if (rw_t2t_is_lock_res_byte(
1513 (uint16_t)(offset + p_t2t->block_read * T2T_BLOCK_LEN)) == false) {
1514 /* Collect the NDEF Message */
1515 p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1516 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001517 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001518 offset++;
1519 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001520
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001521 if (p_t2t->work_offset >= p_t2t->ndef_msg_len) {
1522 done = true;
1523 p_t2t->ndef_status = T2T_NDEF_READ;
1524 } else {
1525 /* Read next 4 blocks */
1526 if (rw_t2t_read((uint16_t)(p_t2t->block_read + T2T_READ_BLOCKS)) !=
1527 NFC_STATUS_OK)
1528 failed = true;
1529 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001530
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001531 if (failed || done) {
1532 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1533 evt_data.p_data = NULL;
1534 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001535 tRW_DATA rw_data;
1536 rw_data.data = evt_data;
1537 (*rw_cb.p_cback)(RW_T2T_NDEF_READ_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001538 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001539}
1540
1541/*******************************************************************************
1542**
1543** Function rw_t2t_handle_ndef_write_rsp
1544**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001545** Description Handle response received to reading (or part of) NDEF
1546** message.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001547**
1548** Returns none
1549**
1550*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001551static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data) {
1552 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1553 tRW_READ_DATA evt_data;
1554 bool failed = false;
1555 bool done = false;
1556 uint16_t block;
1557 uint8_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001558
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001559 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001560 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1561
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001562 /* Backup the read NDEF first block */
1563 memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1564 /* Read ndef final block */
1565 if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
1566 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001567
1568 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1569
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001570 offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
1571 T2T_BLOCK_SIZE;
1572 /* Backup the read NDEF final block */
1573 memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1574 if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
1575 p_t2t->ndef_last_block_num) {
1576 /* If Terminator TLV will reside on the NDEF Final block */
1577 memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
1578 T2T_BLOCK_LEN);
1579 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1580 failed = true;
1581 } else if (p_t2t->terminator_byte_index != 0) {
1582 /* If there is space for Terminator TLV and if it will reside outside
1583 * NDEF Final block */
1584 if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
1585 } else {
1586 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1587 failed = true;
1588 }
1589 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001590
1591 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1592
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001593 offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
1594 p_t2t->block_read) *
1595 T2T_BLOCK_SIZE);
1596 /* Backup the read Terminator TLV block */
1597 memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001598
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001599 /* Write the first block for new NDEF Message */
1600 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1601 failed = true;
1602 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001603
1604 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1605
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001606 offset = (uint8_t)(p_t2t->ndef_read_block_num - p_t2t->block_read) *
1607 T2T_BLOCK_SIZE;
1608 /* Backup read block */
1609 memcpy(p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001610
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001611 /* Update the block with new NDEF Message */
1612 if (rw_t2t_write_ndef_next_block(p_t2t->ndef_read_block_num, 0x0000,
1613 false) != NFC_STATUS_OK)
1614 failed = true;
1615 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001616
1617 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1618 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001619 if (rw_t2t_is_read_before_write_block(
1620 (uint16_t)(p_t2t->block_written + 1), &block) == true) {
1621 p_t2t->ndef_read_block_num = block;
1622 /* If only part of the block is going to be updated read the block to
1623 retain previous data for
1624 unchanged part of the block */
1625 if (rw_t2t_read_ndef_next_block(block) != NFC_STATUS_OK) failed = true;
1626 } else {
1627 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK) {
1628 /* Directly write the block with new NDEF contents as whole block is
1629 * going to be updated */
1630 if (rw_t2t_write_ndef_next_block(block, p_t2t->new_ndef_msg_len,
1631 true) != NFC_STATUS_OK)
1632 failed = true;
1633 } else {
1634 /* Directly write the block with new NDEF contents as whole block is
1635 * going to be updated */
1636 if (rw_t2t_write_ndef_next_block(block, 0x0000, false) !=
1637 NFC_STATUS_OK)
1638 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001639 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001640 }
1641 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001642
1643 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001644 /* Write the next block for new NDEF Message */
1645 p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1646 if (rw_t2t_is_read_before_write_block((uint16_t)(p_t2t->ndef_write_block),
1647 &block) == true) {
1648 /* If only part of the block is going to be updated read the block to
1649 retain previous data for
1650 part of the block thats not going to be changed */
1651 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1652 if (rw_t2t_read(block) != NFC_STATUS_OK) failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001653
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001654 } else {
1655 /* Update NDEF Message Length in the Tag */
1656 if (rw_t2t_write_ndef_first_block(p_t2t->new_ndef_msg_len, true) !=
1657 NFC_STATUS_OK)
1658 failed = true;
1659 }
1660 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001661
1662 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001663 /* Backup read block */
1664 memcpy(p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001665
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001666 /* Update the block with new NDEF Message */
1667 if (rw_t2t_write_ndef_next_block(p_t2t->block_read,
1668 p_t2t->new_ndef_msg_len,
1669 true) == NFC_STATUS_OK)
1670 p_t2t->ndef_write_block = p_t2t->block_read + 1;
1671 else
1672 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001673
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001674 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001675
1676 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001677 if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
1678 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001679
1680 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001681 done = true;
1682 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001683
1684 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001685 break;
1686 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001687
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001688 if (failed || done) {
1689 evt_data.p_data = NULL;
1690 /* NDEF WRITE Operation is done, inform up the stack */
1691 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1692 if (done) {
1693 if ((p_t2t->ndef_msg_len >= 0x00FF) &&
1694 (p_t2t->new_ndef_msg_len < 0x00FF)) {
1695 p_t2t->ndef_msg_offset -= 2;
1696 } else if ((p_t2t->new_ndef_msg_len >= 0x00FF) &&
1697 (p_t2t->ndef_msg_len < 0x00FF)) {
1698 p_t2t->ndef_msg_offset += 2;
1699 }
1700 p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001701 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001702 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001703 tRW_DATA rw_data;
1704 rw_data.data = evt_data;
1705 (*rw_cb.p_cback)(RW_T2T_NDEF_WRITE_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001706 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001707}
1708
1709/*******************************************************************************
1710**
1711** Function rw_t2t_get_tag_size
1712**
1713** Description This function calculates tag data area size from data read
1714** from block with version number
1715**
1716** Returns TMS of the tag
1717**
1718*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001719static uint8_t rw_t2t_get_tag_size(uint8_t* p_data) {
1720 uint16_t LchunkSize = 0;
1721 uint16_t Num_LChuncks = 0;
1722 uint16_t tms = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001723
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001724 LchunkSize = (uint16_t)p_data[2] << 8 | p_data[3];
1725 Num_LChuncks = (uint16_t)p_data[4] << 8 | p_data[5];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001726
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001727 tms = (uint16_t)(LchunkSize * Num_LChuncks);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001728
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001729 tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001730
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001731 tms /= 0x08;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001732
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001733 return (uint8_t)tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001734}
1735
1736/*******************************************************************************
1737**
1738** Function rw_t2t_handle_config_tag_readonly
1739**
1740** Description This function handles configure type 2 tag as read only
1741**
1742** Returns none
1743**
1744*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001745static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data) {
1746 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1747 tNFC_STATUS status = NFC_STATUS_FAILED;
1748 bool b_notify = false;
1749 uint8_t write_block[T2T_BLOCK_SIZE];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001750 bool b_pending = false;
1751 uint8_t read_lock = 0;
1752 uint8_t num_locks = 0;
1753 uint16_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001754
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001755 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001756 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1757
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001758 /* First soft lock the tag */
1759 rw_t2t_soft_lock_tag();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001760
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001761 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001762
1763 case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1764
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001765 /* Successfully soft locked! Update Tag header for future reference */
1766 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1767 if (!p_t2t->b_hard_lock) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001768 /* Tag configuration complete */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001769 status = NFC_STATUS_OK;
Ruchi Kandoi4a179642017-01-04 10:04:48 -08001770 b_notify = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001771 break;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001772 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001773
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001774 /* Coverity: [FALSE-POSITIVE error] intended fall through */
1775 /* Missing break statement between cases in switch statement */
1776 /* fall through */
1777 case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001778
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001779 num_locks = 0;
1780
1781 while (num_locks < p_t2t->num_lockbytes) {
1782 if (p_t2t->lockbyte[num_locks].lock_status ==
1783 RW_T2T_LOCK_UPDATE_INITIATED) {
1784 /* Update control block as one or more dynamic lock byte (s) are set
1785 */
1786 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1787 }
1788 if (!b_pending &&
1789 p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
1790 /* One or more dynamic lock bits are not set */
1791 b_pending = true;
1792 read_lock = num_locks;
1793 }
1794 num_locks++;
1795 }
1796
1797 if (b_pending) {
1798 /* Read the block where dynamic lock bits are present to avoid writing
1799 * to NDEF bytes in the same block */
1800 offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
1801 p_t2t->lockbyte[read_lock].byte_index;
1802 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1803 status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
1804 } else {
1805 /* Now set Static lock bits as no more dynamic lock bits to set */
1806
1807 /* Copy the internal bytes */
1808 memcpy(write_block,
1809 &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
1810 T2T_INTERNAL_BYTES_LEN);
1811 /* Set all Static lock bits */
1812 write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1813 write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1814 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1815 status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1816 }
1817 break;
1818
1819 case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1820 /* Now set the dynamic lock bits present in the block read now */
1821 status = rw_t2t_set_dynamic_lock_bits(p_data);
1822 break;
1823
1824 case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1825 /* Tag configuration complete */
1826 status = NFC_STATUS_OK;
1827 b_notify = true;
1828 break;
1829 }
1830
1831 if (status != NFC_STATUS_OK || b_notify) {
1832 /* Notify upper layer the result of Configuring Tag as Read only */
Myles Watson1361d522017-09-26 13:39:54 -07001833 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001834 evt.status = status;
1835 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001836 (*rw_cb.p_cback)(RW_T2T_SET_TAG_RO_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001837 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001838}
1839
1840/*******************************************************************************
1841**
1842** Function rw_t2t_handle_format_tag_rsp
1843**
1844** Description This function handles formating a type 2 tag
1845**
1846** Returns none
1847**
1848*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001849static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001850 uint8_t* p;
1851 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1852 tNFC_STATUS status = NFC_STATUS_FAILED;
1853 uint16_t version_no;
1854 const tT2T_INIT_TAG* p_ret;
1855 uint8_t tms;
1856 uint8_t next_block = T2T_FIRST_DATA_BLOCK + 1;
1857 uint16_t addr, locked_area;
1858 bool b_notify = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001859
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001860 p = p_t2t->ndef_final_block;
1861 UINT8_TO_BE_STREAM(p, p_t2t->tlv_value[2]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001862
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001863 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001864 case RW_T2T_SUBSTATE_WAIT_READ_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001865 /* Start format operation */
1866 status = rw_t2t_format_tag();
1867 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001868
1869 case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1870
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001871 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1872 p_t2t->b_read_data = true;
1873 version_no = (uint16_t)p_data[0] << 8 | p_data[1];
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001874 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no);
1875 if (p_ret != NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001876 /* Valid Version Number */
1877 if (p_ret->b_calc_cc) /* Calculate tag size from Version Information */
1878 tms = rw_t2t_get_tag_size(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001879
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001880 else
1881 /* Tag size from Look up table */
1882 tms = p_ret->tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001883
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001884 /* Set CC with the Tag size from look up table or from calculated value
1885 */
1886 status = rw_t2t_set_cc(tms);
1887 }
1888 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001889
1890 case RW_T2T_SUBSTATE_WAIT_SET_CC:
1891
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001892 version_no = (uint16_t)p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1893 if ((version_no == 0) ||
1894 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) ==
1895 NULL) ||
1896 (!p_ret->b_multi_version) || (!p_ret->b_calc_cc)) {
1897 /* Currently Formating a non blank tag or a blank tag with manufacturer
1898 * has only one variant of tag. Set Null NDEF TLV and complete Format
1899 * Operation */
1900 next_block = T2T_FIRST_DATA_BLOCK;
1901 p = p_t2t->ndef_final_block;
1902 } else {
1903 addr = (uint16_t)(
1904 ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1905 ((uint16_t)p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) +
1906 T2T_STATIC_SIZE);
1907 locked_area = ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1908 ((uint16_t)p_t2t->tag_data[6]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001909
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001910 status = rw_t2t_set_lock_tlv(addr, p_t2t->tag_data[7], locked_area);
1911 if (status == NFC_STATUS_REJECTED) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001912 /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format
1913 * Operation */
1914 next_block = T2T_FIRST_DATA_BLOCK;
1915 p = p_t2t->ndef_final_block;
1916 } else
1917 break;
1918 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001919
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001920 /* falls through */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001921 case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
1922
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001923 /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
1924 UINT8_TO_BE_STREAM(p, TAG_NDEF_TLV);
1925 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001926
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001927 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1928 (!p_ret->b_otp)) {
1929 UINT8_TO_BE_STREAM(p, TAG_TERMINATOR_TLV);
1930 } else
1931 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001932
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001933 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
1934 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001935 status = rw_t2t_write(next_block, p_t2t->ndef_final_block);
1936 if (status == NFC_STATUS_OK) p_t2t->b_read_data = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001937 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001938
1939 case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001940 /* Tag Formated successfully */
1941 status = NFC_STATUS_OK;
1942 b_notify = true;
1943 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001944
1945 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001946 break;
1947 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001948
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001949 if (status != NFC_STATUS_OK || b_notify) {
1950 /* Notify upper layer the result of Format op */
Myles Watson1361d522017-09-26 13:39:54 -07001951 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001952 evt.status = status;
1953 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001954 (*rw_cb.p_cback)(RW_T2T_FORMAT_CPLT_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001955 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001956}
1957
1958/*******************************************************************************
1959**
1960** Function rw_t2t_update_attributes
1961**
1962** Description This function will update attribute for the current segment
1963** based on lock and reserved bytes
1964**
1965** Returns None
1966**
1967*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001968static void rw_t2t_update_attributes(void) {
1969 uint8_t count = 0;
1970 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1971 uint16_t lower_offset;
1972 uint16_t upper_offset;
1973 uint16_t offset;
1974 uint8_t num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001975
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001976 /* Prepare attr for the current segment */
1977 memset(p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001978
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001979 /* calculate offset where the current segment starts in the tag */
1980 lower_offset = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
1981 /* calculate offset where the current segment ends in the tag */
1982 upper_offset = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001983
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001984 /* check offset of lock bytes in the tag and update p_t2t->attr
1985 * for every lock byte that is present in the current segment */
1986 count = 0;
1987 while (count < p_t2t->num_lockbytes) {
1988 offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset +
1989 p_t2t->lockbyte[count].byte_index;
1990 if (offset >= lower_offset && offset < upper_offset) {
1991 /* Calculate offset in the current segment as p_t2t->attr is prepared for
1992 * one segment only */
1993 offset %= RW_T2T_SEGMENT_BYTES;
1994 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1995 * lock/reserved byte or not
1996 * So, each array element in p_t2t->attr covers two blocks in the tag as
1997 * T2 block size is 4 and array element size is 8
1998 * Set the corresponding bit in attr to indicate - reserved byte */
1999 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
2000 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002001 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002002 count++;
2003 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002004
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002005 /* Search reserved bytes identified by all memory tlvs present in the tag */
2006 count = 0;
2007 while (count < p_t2t->num_mem_tlvs) {
2008 /* check the offset of reserved bytes in the tag and update p_t2t->attr
2009 * for every reserved byte that is present in the current segment */
2010 num_bytes = 0;
2011 while (num_bytes < p_t2t->mem_tlv[count].num_bytes) {
2012 offset = p_t2t->mem_tlv[count].offset + num_bytes;
2013 if (offset >= lower_offset && offset < upper_offset) {
2014 /* Let offset represents offset in the current segment as p_t2t->attr is
2015 * prepared for one segment only */
2016 offset %= RW_T2T_SEGMENT_BYTES;
2017 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
2018 * lock/reserved byte or not
2019 * So, each array element in p_t2t->attr covers two blocks in the tag as
2020 * T2 block size is 4 and array element size is 8
2021 * Set the corresponding bit in attr to indicate - reserved byte */
2022 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
2023 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
2024 }
2025 num_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002026 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002027 count++;
2028 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002029}
2030
2031/*******************************************************************************
2032**
2033** Function rw_t2t_get_lock_bits_for_segment
2034**
2035** Description This function returns the offset of lock bits associated for
2036** the specified segment
2037**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002038** Parameters: segment: The segment number to which lock bits are
2039** associated
2040** p_start_byte: The offset of lock byte that contains the
2041** first lock bit for the segment
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002042** p_start_bit: The offset of the lock bit in the lock byte
2043**
2044** p_end_byte: The offset of the last bit associcated to the
2045** segment
2046**
2047** Returns Total number of lock bits assigned to the specified segment
2048**
2049*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002050static uint8_t rw_t2t_get_lock_bits_for_segment(uint8_t segment,
2051 uint8_t* p_start_byte,
2052 uint8_t* p_start_bit,
2053 uint8_t* p_end_byte) {
2054 uint8_t total_bits = 0;
2055 uint16_t byte_count = 0;
2056 uint16_t lower_offset, upper_offset;
2057 uint8_t num_dynamic_locks = 0;
2058 uint8_t bit_count = 0;
2059 uint8_t bytes_locked_per_bit;
2060 uint8_t num_bits;
2061 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2062 bool b_all_bits_are_locks = true;
2063 uint16_t tag_size;
2064 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002065
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002066 tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
2067 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002068
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002069 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2070 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002071
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002072 lower_offset = segment * RW_T2T_SEGMENT_BYTES;
2073 if (segment == 0) {
2074 lower_offset += T2T_STATIC_SIZE;
2075 }
2076 upper_offset = (segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002077
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002078 byte_count = T2T_STATIC_SIZE;
2079 if (tag_size < upper_offset) {
2080 upper_offset = tag_size;
2081 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002082
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002083 *p_start_byte = num_dynamic_locks;
2084 *p_start_bit = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002085
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002086 while ((byte_count <= lower_offset) &&
2087 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2088 bytes_locked_per_bit =
2089 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2090 .bytes_locked_per_bit;
2091 /* Number of bits in the current lock byte */
2092 b_all_bits_are_locks =
2093 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2094 TAG_BITS_PER_BYTE <=
2095 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2096 .num_bits);
2097 num_bits =
2098 b_all_bits_are_locks
2099 ? TAG_BITS_PER_BYTE
2100 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2101 .num_bits %
2102 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002103
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002104 if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset) {
2105 /* Skip this lock byte as it covers different segment */
2106 byte_count += bytes_locked_per_bit * num_bits;
2107 num_dynamic_locks++;
2108 } else {
2109 bit_count = 0;
2110 while (bit_count < num_bits) {
2111 byte_count += bytes_locked_per_bit;
2112 if (byte_count > lower_offset) {
2113 /* First lock bit that is used to lock this segment */
2114 *p_start_byte = num_dynamic_locks;
2115 *p_end_byte = num_dynamic_locks;
2116 *p_start_bit = bit_count;
2117 bit_count++;
2118 total_bits = 1;
2119 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002120 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002121 bit_count++;
2122 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002123 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002124 }
2125 if (num_dynamic_locks == p_t2t->num_lockbytes) {
2126 return 0;
2127 }
2128 while ((byte_count < upper_offset) &&
2129 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2130 bytes_locked_per_bit =
2131 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2132 .bytes_locked_per_bit;
2133 /* Number of bits in the current lock byte */
2134 b_all_bits_are_locks =
2135 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2136 TAG_BITS_PER_BYTE <=
2137 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2138 .num_bits);
2139 num_bits =
2140 b_all_bits_are_locks
2141 ? TAG_BITS_PER_BYTE
2142 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2143 .num_bits %
2144 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002145
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002146 if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count <
2147 upper_offset) {
2148 /* Collect all lock bits that covers the current segment */
2149 byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2150 total_bits += num_bits - bit_count;
2151 bit_count = 0;
2152 *p_end_byte = num_dynamic_locks;
2153 num_dynamic_locks++;
2154 } else {
2155 /* The last lock byte that covers the current segment */
2156 bit_count = 0;
2157 while (bit_count < num_bits) {
2158 /* The last lock bit that is used to lock this segment */
2159 byte_count += bytes_locked_per_bit;
2160 if (byte_count >= upper_offset) {
2161 *p_end_byte = num_dynamic_locks;
2162 total_bits += (bit_count + 1);
2163 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002164 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002165 bit_count++;
2166 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002167 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002168 }
2169 return total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002170}
2171
2172/*******************************************************************************
2173**
2174** Function rw_t2t_update_lock_attributes
2175**
2176** Description This function will check if the tag index passed as
2177** argument is a locked byte and return TRUE or FALSE
2178**
2179** Parameters: index, the index of the byte in the tag
2180**
2181**
2182** Returns TRUE, if the specified index in the tag is a locked or
2183** reserved or otp byte
2184** FALSE, otherwise
2185**
2186*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002187static void rw_t2t_update_lock_attributes(void) {
2188 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2189 uint8_t xx = 0;
2190 uint8_t num_static_lock_bytes = 0;
2191 uint8_t num_dyn_lock_bytes = 0;
2192 uint8_t bits_covered = 0;
2193 uint8_t bytes_covered = 0;
2194 uint8_t block_count = 0;
2195 bool b_all_bits_are_locks = true;
2196 uint8_t bytes_locked_per_lock_bit;
2197 uint8_t start_lock_byte;
2198 uint8_t start_lock_bit;
2199 uint8_t end_lock_byte;
2200 uint8_t num_lock_bits;
2201 uint8_t total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002202
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002203 /* Prepare lock_attr for the current segment */
2204 memset(p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002205
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002206 block_count = 0;
2207 if (p_t2t->segment == 0) {
2208 /* Update lock_attributes based on static lock bytes */
2209 xx = 0;
2210 num_static_lock_bytes = 0;
2211 block_count = 0;
2212 num_lock_bits =
2213 TAG_BITS_PER_BYTE - 1; /* the inner while loop increases xx by 2. need
2214 (-1) to avoid coverity overrun error */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002215
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002216 while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES) {
2217 /* Update lock attribute based on 2 static locks */
2218 while (xx < num_lock_bits) {
2219 p_t2t->lock_attr[block_count] = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002220
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002221 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2222 rw_t2t_mask_bits[xx++]) {
2223 /* If the bit is set then 1 block is locked */
2224 p_t2t->lock_attr[block_count] = 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002225 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002226
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002227 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2228 rw_t2t_mask_bits[xx++]) {
2229 /* If the bit is set then 1 block is locked */
2230 p_t2t->lock_attr[block_count] |= 0xF0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002231 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002232 block_count++;
2233 }
2234 num_static_lock_bytes++;
2235 xx = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002236 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002237 /* UID is always locked, irrespective of the lock value */
2238 p_t2t->lock_attr[0x00] = 0xFF;
2239 }
2240
2241 /* Get lock bits applicable for the current segment */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002242 total_bits = rw_t2t_get_lock_bits_for_segment(
2243 p_t2t->segment, &start_lock_byte, &start_lock_bit, &end_lock_byte);
2244 if (total_bits != 0) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002245 /* update lock_attributes based on current segment using dynamic lock bytes
2246 */
2247 xx = start_lock_bit;
2248 num_dyn_lock_bytes = start_lock_byte;
2249 bits_covered = 0;
2250 bytes_covered = 0;
2251 num_lock_bits = TAG_BITS_PER_BYTE;
2252 p_t2t->lock_attr[block_count] = 0;
2253
2254 while (num_dyn_lock_bytes <= end_lock_byte) {
2255 bytes_locked_per_lock_bit =
2256 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2257 .bytes_locked_per_bit;
2258 /* Find number of bits in the byte are lock bits */
2259 b_all_bits_are_locks =
2260 ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) *
2261 TAG_BITS_PER_BYTE <=
2262 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2263 .num_bits);
2264 num_lock_bits =
2265 b_all_bits_are_locks
2266 ? TAG_BITS_PER_BYTE
2267 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2268 .num_bits %
2269 TAG_BITS_PER_BYTE;
2270
2271 while (xx < num_lock_bits) {
2272 bytes_covered = 0;
2273 while (bytes_covered < bytes_locked_per_lock_bit) {
2274 if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte &
2275 rw_t2t_mask_bits[xx]) {
2276 /* If the bit is set then it is locked */
Alisher Alikhodjaeva639b702020-01-29 20:34:26 -08002277 if (block_count < RW_T2T_SEGMENT_SIZE)
2278 p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002279 }
2280 bytes_covered++;
2281 bits_covered++;
2282 if (bits_covered == TAG_BITS_PER_BYTE) {
2283 /* Move to next 8 bytes */
2284 bits_covered = 0;
2285 block_count++;
2286 /* Assume unlocked before updating using locks */
2287 if (block_count < RW_T2T_SEGMENT_SIZE)
2288 p_t2t->lock_attr[block_count] = 0;
2289 }
2290 }
2291 xx++;
2292 }
2293 num_dyn_lock_bytes++;
2294 xx = 0;
2295 }
2296 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002297}
2298
2299/*******************************************************************************
2300**
2301** Function rw_t2t_is_lock_res_byte
2302**
2303** Description This function will check if the tag index passed as
2304** argument is a lock or reserved or otp byte and return
2305** TRUE or FALSE
2306**
2307** Parameters: index, the index of the byte in the tag
2308**
2309**
2310** Returns TRUE, if the specified index in the tag is a locked or
2311** reserved or otp byte
2312** FALSE, otherwise
2313**
2314*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002315static bool rw_t2t_is_lock_res_byte(uint16_t index) {
2316 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002317
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002318 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002319
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002320 if (p_t2t->attr_seg != p_t2t->segment) {
2321 /* Update attributes for the current segment */
2322 rw_t2t_update_attributes();
2323 p_t2t->attr_seg = p_t2t->segment;
2324 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002325
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002326 index = index % RW_T2T_SEGMENT_BYTES;
2327 /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a
2328 * lock/reserved byte or not
2329 * So, each array element in p_t2t->attr covers two blocks in the tag as T2
2330 * block size is 4 and array element size is 8
2331 * Find the block and offset for the index (passed as argument) and Check if
2332 * the offset bit in the
2333 * p_t2t->attr[block/2] is set or not. If the bit is set then it is a
2334 * lock/reserved byte, otherwise not */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002335
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002336 return ((p_t2t->attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0) ? false
2337 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002338}
2339
2340/*******************************************************************************
2341**
2342** Function rw_t2t_is_read_only_byte
2343**
2344** Description This function will check if the tag index passed as
2345** argument is a locked and return
2346** TRUE or FALSE
2347**
2348** Parameters: index, the index of the byte in the tag
2349**
2350**
2351** Returns TRUE, if the specified index in the tag is a locked or
2352** reserved or otp byte
2353** FALSE, otherwise
2354**
2355*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002356static bool rw_t2t_is_read_only_byte(uint16_t index) {
2357 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002358
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002359 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002360
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002361 if (p_t2t->lock_attr_seg != p_t2t->segment) {
2362 /* Update lock attributes for the current segment */
2363 rw_t2t_update_lock_attributes();
2364 p_t2t->lock_attr_seg = p_t2t->segment;
2365 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002366
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002367 index = index % RW_T2T_SEGMENT_BYTES;
2368 /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a
2369 * read only byte or read write byte
2370 * So, each array element in p_t2t->lock_attr covers two blocks of the tag as
2371 * T2 block size is 4 and array element size is 8
2372 * Find the block and offset for the index (passed as argument) and Check if
2373 * the offset bit in
2374 * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a
2375 * read only byte, otherwise read write byte */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002376
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002377 return ((p_t2t->lock_attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0)
2378 ? false
2379 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002380}
2381
2382/*******************************************************************************
2383**
2384** Function rw_t2t_set_dynamic_lock_bits
2385**
2386** Description This function will set dynamic lock bits as part of
2387** configuring tag as read only
2388**
2389** Returns
2390** NFC_STATUS_OK, Command sent to set dynamic lock bits
2391** NFC_STATUS_FAILED: otherwise
2392**
2393*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002394tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data) {
2395 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2396 uint8_t write_block[T2T_BLOCK_SIZE];
2397 uint16_t offset;
2398 uint16_t next_offset;
2399 uint8_t num_bits;
2400 uint8_t next_num_bits;
2401 tNFC_STATUS status = NFC_STATUS_FAILED;
2402 uint8_t num_locks;
2403 uint8_t lock_count;
2404 bool b_all_bits_are_locks = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002405
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002406 num_locks = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002407
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002408 memcpy(write_block, p_data, T2T_BLOCK_SIZE);
2409 while (num_locks < p_t2t->num_lockbytes) {
2410 if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
2411 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
2412 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002413
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002414 /* Check if all bits are lock bits in the byte */
2415 b_all_bits_are_locks =
2416 ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <=
2417 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2418 num_bits =
2419 b_all_bits_are_locks
2420 ? TAG_BITS_PER_BYTE
2421 : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits %
2422 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002423
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002424 write_block[(uint8_t)(offset % T2T_BLOCK_SIZE)] |=
2425 tags_pow(2, num_bits) - 1;
2426 lock_count = num_locks + 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002427
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002428 /* Set all the lock bits in the block using a sing block write command */
2429 while (lock_count < p_t2t->num_lockbytes) {
2430 next_offset =
2431 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset +
2432 p_t2t->lockbyte[lock_count].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002433
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002434 /* Check if all bits are lock bits in the byte */
2435 b_all_bits_are_locks =
2436 ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <=
2437 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2438 next_num_bits =
2439 b_all_bits_are_locks
2440 ? TAG_BITS_PER_BYTE
2441 : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index]
2442 .num_bits %
2443 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002444
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002445 if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE) {
2446 write_block[(uint8_t)(next_offset % T2T_BLOCK_SIZE)] |=
2447 tags_pow(2, next_num_bits) - 1;
2448 } else
2449 break;
2450 lock_count++;
2451 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002452
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002453 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2454 /* send WRITE command to set dynamic lock bits */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002455 status = rw_t2t_write((uint16_t)(offset / T2T_BLOCK_SIZE), write_block);
2456 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002457 while (lock_count > num_locks) {
2458 /* Set update initiated flag to indicate a write command is sent to
2459 * set dynamic lock bits of the block */
2460 p_t2t->lockbyte[lock_count - 1].lock_status =
2461 RW_T2T_LOCK_UPDATE_INITIATED;
2462 lock_count--;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002463 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002464 } else
2465 status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002466
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002467 break;
2468 }
2469 num_locks++;
2470 }
2471
2472 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002473}
2474
2475/*******************************************************************************
2476**
2477** Function rw_t2t_set_lock_tlv
2478**
2479** Description This function will set lock control tlv on the blank
2480** activated type 2 tag based on values read from version block
2481**
2482** Parameters: TAG data memory size
2483**
2484** Returns
2485** NFC_STATUS_OK, Command sent to set Lock TLV
2486** NFC_STATUS_FAILED: otherwise
2487**
2488*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002489tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
2490 uint16_t locked_area_size) {
2491 tNFC_STATUS status = NFC_STATUS_FAILED;
2492 int8_t PageAddr = 0;
2493 int8_t BytePerPage = 0;
2494 int8_t ByteOffset = 0;
2495 uint8_t a;
2496 uint8_t data_block[T2T_BLOCK_SIZE];
2497 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2498 uint8_t* p;
2499 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002500
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002501 for (xx = 15; xx > 0; xx--) {
2502 a = (uint8_t)(addr / xx);
2503 a += (addr % xx) ? 1 : 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002504
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002505 BytePerPage = (int8_t)tags_log2(a);
2506 ByteOffset = (int8_t)(addr - xx * tags_pow(2, BytePerPage));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002507
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002508 if (ByteOffset < 16) {
2509 PageAddr = xx;
2510 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002511 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002512 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002513
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002514 if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16)) {
2515 memset(data_block, 0, T2T_BLOCK_SIZE);
2516 p = data_block;
2517 UINT8_TO_BE_STREAM(p, T2T_TLV_TYPE_LOCK_CTRL);
2518 UINT8_TO_BE_STREAM(p, T2T_TLEN_LOCK_CTRL_TLV);
2519 UINT8_TO_BE_STREAM(p, (PageAddr << 4 | ByteOffset));
2520 UINT8_TO_BE_STREAM(p, num_dyn_lock_bits);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002521
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002522 p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2523 p_t2t->tlv_value[1] = num_dyn_lock_bits;
2524 p_t2t->tlv_value[2] =
2525 (uint8_t)(BytePerPage << 4 | tags_log2(locked_area_size));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002526
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002527 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002528
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002529 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002530 status = rw_t2t_write(T2T_FIRST_DATA_BLOCK, data_block);
2531 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002532 p_t2t->b_read_data = false;
2533 } else
2534 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2535 } else
2536 status = NFC_STATUS_REJECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002537
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002538 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002539}
2540
2541/*******************************************************************************
2542**
2543** Function rw_t2t_set_cc
2544**
2545** Description This function will set Capability Container on the activated
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002546** type 2 tag with default values of CC0, CC1, CC4 and
2547** specified CC3 value
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002548**
2549** Parameters: CC3 value of the tag
2550**
2551** Returns
2552** NFC_STATUS_OK, Command sent to set CC
2553** NFC_STATUS_FAILED: otherwise
2554**
2555*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002556tNFC_STATUS rw_t2t_set_cc(uint8_t tms) {
2557 uint8_t cc_block[T2T_BLOCK_SIZE];
2558 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2559 tNFC_STATUS status = NFC_STATUS_FAILED;
2560 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002561
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002562 memset(cc_block, 0, T2T_BLOCK_SIZE);
2563 memset(p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2564 p = cc_block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002565
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002566 /* Prepare Capability Container */
2567 UINT8_TO_BE_STREAM(p, T2T_CC0_NMN);
2568 UINT8_TO_BE_STREAM(p, T2T_CC1_VNO);
2569 UINT8_TO_BE_STREAM(p, tms);
2570 UINT8_TO_BE_STREAM(p, T2T_CC3_RWA_RW);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002571
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002572 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002573
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002574 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002575 status = rw_t2t_write(T2T_CC_BLOCK, cc_block);
2576 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002577 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2578 p_t2t->b_read_hdr = false;
2579 } else
2580 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002581
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002582 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002583}
2584
2585/*******************************************************************************
2586**
2587** Function rw_t2t_format_tag
2588**
2589** Description This function will format tag based on Manufacturer ID
2590**
2591** Returns
2592** NFC_STATUS_OK, Command sent to format Tag
2593** NFC_STATUS_FAILED: otherwise
2594**
2595*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002596tNFC_STATUS rw_t2t_format_tag(void) {
2597 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2598 const tT2T_INIT_TAG* p_ret;
2599 uint8_t tms;
2600 tNFC_STATUS status = NFC_STATUS_FAILED;
2601 bool b_blank_tag = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002602
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002603 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
2604 if (p_ret == NULL) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002605 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002606 "rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the "
2607 "tag!",
2608 p_t2t->tag_hdr[0]);
2609 return (NFC_STATUS_FAILED);
2610 }
2611
2612 if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0) {
2613 /* If OTP tag has valid NDEF Message, cannot format the tag */
2614 if ((p_t2t->ndef_msg_len > 0) && (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002615 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002616 "rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2617 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002618 }
2619
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002620 if (((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) &&
2621 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) ||
2622 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) &&
2623 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
2624 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
2625 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002626 LOG(WARNING) << StringPrintf(
2627 "rw_t2t_format_tag - Tag not blank to Format!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002628 return (NFC_STATUS_FAILED);
2629 } else {
2630 tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2631 b_blank_tag = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002632 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002633 } else
2634 tms = p_ret->tms;
2635
2636 memset(p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2637
2638 if (!b_blank_tag || !p_ret->b_multi_version) {
2639 status = rw_t2t_set_cc(tms);
2640 } else if (p_ret->version_block != 0) {
2641 /* If Version number is not read, READ it now */
2642 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2643
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002644 status = rw_t2t_read(p_ret->version_block);
2645 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002646 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002647 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002648 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2649 } else {
2650 /* UID block is the version block */
2651 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2652 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2653 rw_t2t_handle_format_tag_rsp(p_t2t->tag_hdr);
2654 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002655
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002656 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002657}
2658
2659/*******************************************************************************
2660**
2661** Function rw_t2t_soft_lock_tag
2662**
2663** Description This function will soft lock the tag after validating CC.
2664**
2665** Returns
2666** NFC_STATUS_OK, Command sent to soft lock the tag
2667** NFC_STATUS_FAILED: otherwise
2668**
2669*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002670tNFC_STATUS rw_t2t_soft_lock_tag(void) {
2671 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2672 tNFC_STATUS status = NFC_STATUS_FAILED;
2673 uint8_t write_block[T2T_BLOCK_SIZE];
2674 uint8_t num_locks;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002675
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002676 /* If CC block is read and cc3 is soft locked, reject the command */
2677 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002678 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002679 "rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: "
2680 "%u",
2681 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2682 return (NFC_STATUS_FAILED);
2683 }
2684
2685 if (p_t2t->b_hard_lock) {
2686 /* Should have performed NDEF Detection on dynamic memory structure tag,
2687 * before permanently converting to Read only
2688 * Even when no lock control tlv is present, default lock bytes should be
2689 * present */
2690
2691 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) &&
2692 (p_t2t->num_lockbytes == 0)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002693 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002694 "rw_t2t_soft_lock_tag: Error: Lock TLV not detected! Cannot hard "
2695 "lock the tag");
2696 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002697 }
2698
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002699 /* On dynamic memory structure tag, reset all lock bytes status to 'Not
2700 * Updated' if not in Updated status */
2701 num_locks = 0;
2702 while (num_locks < p_t2t->num_lockbytes) {
2703 if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2704 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2705 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002706 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002707 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002708
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002709 memcpy(write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2710 write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002711
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002712 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2713 /* First Soft lock the tag */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002714 status = rw_t2t_write(T2T_CC_BLOCK, write_block);
2715 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002716 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
2717 p_t2t->b_read_hdr = false;
2718 } else {
2719 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2720 }
2721 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002722}
2723
2724/*****************************************************************************
2725**
2726** Function RW_T2tFormatNDef
2727**
2728** Description
2729** Format Tag content
2730**
2731** Returns
2732** NFC_STATUS_OK, Command sent to format Tag
2733** NFC_STATUS_FAILED: otherwise
2734**
2735*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002736tNFC_STATUS RW_T2tFormatNDef(void) {
2737 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2738 tNFC_STATUS status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002739
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002740 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002741 LOG(WARNING) << StringPrintf(
2742 "RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u",
2743 p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002744 return (NFC_STATUS_FAILED);
2745 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002746
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002747 if (!p_t2t->b_read_hdr) {
2748 /* If UID is not read, READ it now */
2749 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002750
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002751 status = rw_t2t_read(0);
2752 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002753 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002754 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002755 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2756 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002757 status = rw_t2t_format_tag();
2758 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002759 }
2760 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002761}
2762
2763/*******************************************************************************
2764**
2765** Function RW_T2tLocateTlv
2766**
2767** Description This function is used to perform TLV detection on a Type 2
2768** tag, and retrieve the tag's TLV attribute information.
2769**
2770** Before using this API, the application must call
2771** RW_SelectTagType to indicate that a Type 2 tag has been
2772** activated.
2773**
2774** Parameters: tlv_type : TLV to detect
2775**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002776** Returns NCI_STATUS_OK, if detection was started. Otherwise, error
2777** status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002778**
2779*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002780tNFC_STATUS RW_T2tLocateTlv(uint8_t tlv_type) {
2781 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2782 tNFC_STATUS status;
2783 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002784
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002785 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002786 LOG(ERROR) << StringPrintf(
2787 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002788 return (NFC_STATUS_BUSY);
2789 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002790
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002791 if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) &&
2792 (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002793 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2794 "RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002795 return (NFC_STATUS_FAILED);
2796 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002797
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002798 if ((tlv_type == TAG_LOCK_CTRL_TLV) && (p_t2t->b_read_hdr) &&
2799 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)) {
2800 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002801 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002802 "RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x",
2803 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2804 return (NFC_STATUS_FAILED);
2805 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002806
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002807 if ((tlv_type == TAG_NDEF_TLV) && (p_t2t->b_read_hdr) &&
2808 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) {
2809 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002810 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002811 "RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: "
2812 "0x%02x, CC[3]: 0x%02x",
2813 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
2814 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2815 return (NFC_STATUS_FAILED);
2816 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002817
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002818 p_t2t->work_offset = 0;
2819 p_t2t->tlv_detect = tlv_type;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002820
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002821 /* Reset control block variables based on type of tlv to detect */
2822 if (tlv_type == TAG_LOCK_CTRL_TLV) {
2823 p_t2t->num_lockbytes = 0;
2824 p_t2t->num_lock_tlvs = 0;
2825 } else if (tlv_type == TAG_MEM_CTRL_TLV) {
2826 p_t2t->num_mem_tlvs = 0;
2827 } else if (tlv_type == TAG_NDEF_TLV) {
2828 p_t2t->ndef_msg_offset = 0;
2829 p_t2t->num_lockbytes = 0;
2830 p_t2t->num_lock_tlvs = 0;
2831 p_t2t->num_mem_tlvs = 0;
2832 p_t2t->ndef_msg_len = 0;
2833 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
2834 } else {
2835 p_t2t->prop_msg_len = 0;
2836 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002837
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002838 if (!p_t2t->b_read_hdr) {
2839 /* First read CC block */
2840 block = 0;
2841 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2842 } else {
2843 /* Read first data block */
2844 block = T2T_FIRST_DATA_BLOCK;
2845 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2846 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002847
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002848 /* Start reading tag, looking for the specified TLV */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002849 status = rw_t2t_read((uint16_t)block);
2850 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002851 p_t2t->state = RW_T2T_STATE_DETECT_TLV;
2852 } else {
2853 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2854 }
2855 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002856}
2857
2858/*******************************************************************************
2859**
2860** Function RW_T2tDetectNDef
2861**
2862** Description This function is used to perform NDEF detection on a Type 2
2863** tag, and retrieve the tag's NDEF attribute information.
2864**
2865** Before using this API, the application must call
2866** RW_SelectTagType to indicate that a Type 2 tag has been
2867** activated.
2868**
2869** Parameters: none
2870**
2871** Returns NCI_STATUS_OK,if detect op started.Otherwise,error status.
2872**
2873*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002874tNFC_STATUS RW_T2tDetectNDef(bool skip_dyn_locks) {
2875 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Evan Chuc95c79c2013-04-12 17:38:09 -04002876
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002877 p_t2t->skip_dyn_locks = skip_dyn_locks;
Evan Chuc95c79c2013-04-12 17:38:09 -04002878
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002879 return RW_T2tLocateTlv(TAG_NDEF_TLV);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002880}
2881
2882/*******************************************************************************
2883**
2884** Function RW_T2tReadNDef
2885**
2886** Description Retrieve NDEF contents from a Type2 tag.
2887**
2888** The RW_T2T_NDEF_READ_EVT event is used to notify the
2889** application after reading the NDEF message.
2890**
2891** Before using this API, the RW_T2tDetectNDef function must
2892** be called to verify that the tag contains NDEF data, and to
2893** retrieve the NDEF attributes.
2894**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002895** Internally, this command will be separated into multiple
2896** Tag2 Read commands (if necessary) - depending on the NDEF
2897** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002898**
2899** Parameters: p_buffer: The buffer into which to read the NDEF message
2900** buf_len: The length of the buffer
2901**
2902** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
2903**
2904*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002905tNFC_STATUS RW_T2tReadNDef(uint8_t* p_buffer, uint16_t buf_len) {
2906 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2907 tNFC_STATUS status = NFC_STATUS_OK;
2908 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002909
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002910 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002911 LOG(ERROR) << StringPrintf(
2912 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002913 return (NFC_STATUS_FAILED);
2914 }
2915
2916 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002917 LOG(ERROR) << StringPrintf(
2918 "RW_T2tReadNDef - Error: NDEF detection not performed yet");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002919 return (NFC_STATUS_FAILED);
2920 }
2921
2922 if (buf_len < p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002923 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002924 "RW_T2tReadNDef - buffer size: %u less than NDEF msg sise: %u",
2925 buf_len, p_t2t->ndef_msg_len);
2926 return (NFC_STATUS_FAILED);
2927 }
2928
2929 if (!p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002930 LOG(WARNING) << StringPrintf(
2931 "RW_T2tReadNDef - NDEF Message length is zero");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002932 return (NFC_STATUS_NOT_INITIALIZED);
2933 }
2934
2935 p_t2t->p_ndef_buffer = p_buffer;
2936 p_t2t->work_offset = 0;
2937
2938 block = (uint16_t)(p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
2939 block -= block % T2T_READ_BLOCKS;
2940
2941 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2942
2943 if ((block == T2T_FIRST_DATA_BLOCK) && (p_t2t->b_read_data)) {
2944 p_t2t->state = RW_T2T_STATE_READ_NDEF;
2945 p_t2t->block_read = T2T_FIRST_DATA_BLOCK;
2946 rw_t2t_handle_ndef_read_rsp(p_t2t->tag_data);
2947 } else {
2948 /* Start reading NDEF Message */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002949 status = rw_t2t_read(block);
2950 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002951 p_t2t->state = RW_T2T_STATE_READ_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002952 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002953 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002954
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002955 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002956}
2957
2958/*******************************************************************************
2959**
2960** Function RW_T2tWriteNDef
2961**
2962** Description Write NDEF contents to a Type2 tag.
2963**
2964** Before using this API, the RW_T2tDetectNDef
2965** function must be called to verify that the tag contains
2966** NDEF data, and to retrieve the NDEF attributes.
2967**
2968** The RW_T2T_NDEF_WRITE_EVT callback event will be used to
2969** notify the application of the response.
2970**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002971** Internally, this command will be separated into multiple
2972** Tag2 Write commands (if necessary) - depending on the NDEF
2973** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002974**
2975** Parameters: msg_len: The length of the buffer
2976** p_msg: The NDEF message to write
2977**
2978** Returns NCI_STATUS_OK,if write was started. Otherwise, error status
2979**
2980*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002981tNFC_STATUS RW_T2tWriteNDef(uint16_t msg_len, uint8_t* p_msg) {
2982 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2983 uint16_t block;
2984 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002985
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002986 tNFC_STATUS status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002987
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002988 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002989 LOG(ERROR) << StringPrintf(
2990 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002991 return (NFC_STATUS_FAILED);
2992 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002993
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002994 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002995 LOG(ERROR) << StringPrintf(
2996 "RW_T2tWriteNDef - Error: NDEF detection not performed!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002997 return (NFC_STATUS_FAILED);
2998 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002999
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003000 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003001 LOG(ERROR) << StringPrintf(
3002 "RW_T2tWriteNDef - Write access not granted - CC3: %u",
3003 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003004 return (NFC_STATUS_REFUSED);
3005 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07003006
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003007 /* Check if there is enough memory on the tag */
3008 if (msg_len > p_t2t->max_ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003009 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003010 "RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes",
3011 p_t2t->max_ndef_msg_len);
3012 return (NFC_STATUS_FAILED);
3013 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003014
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003015 /* If OTP tag and tag has valid NDEF Message, stop writting new NDEF Message
3016 * as it may corrupt the tag */
3017 if ((p_t2t->ndef_msg_len > 0) &&
3018 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
3019 (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003020 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003021 "RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
3022 return (NFC_STATUS_FAILED);
3023 }
3024 p_t2t->p_new_ndef_buffer = p_msg;
3025 p_t2t->new_ndef_msg_len = msg_len;
3026 p_t2t->work_offset = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003027
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003028 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
3029 /* Read first NDEF Block before updating NDEF */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003030
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003031 block = (uint16_t)(p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003032
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003033 if ((block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) &&
3034 (p_t2t->b_read_data)) {
3035 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
3036 p_t2t->block_read = block;
3037 rw_t2t_handle_ndef_write_rsp(
3038 &p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
3039 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003040 status = rw_t2t_read(block);
3041 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003042 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003043 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003044 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3045 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003046
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003047 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003048}
3049
3050/*******************************************************************************
3051**
3052** Function RW_T2tSetTagReadOnly
3053**
3054** Description This function can be called to set T2 tag as read only.
3055**
3056** Parameters: b_hard_lock: To indicate hard lock the tag or not
3057**
3058** Returns NCI_STATUS_OK, if setting tag as read only was started.
3059** Otherwise, error status.
3060**
3061*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003062tNFC_STATUS RW_T2tSetTagReadOnly(bool b_hard_lock) {
3063 tNFC_STATUS status = NFC_STATUS_FAILED;
3064 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003065
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003066 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003067 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003068 "RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - "
3069 "State: %u",
3070 p_t2t->state);
3071 return (NFC_STATUS_FAILED);
3072 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003073
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003074 p_t2t->b_hard_lock = b_hard_lock;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003075
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003076 if (!p_t2t->b_read_hdr) {
3077 /* Read CC block before configuring tag as Read only */
3078 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003079 status = rw_t2t_read((uint16_t)0);
3080 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003081 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
3082 } else
3083 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3084 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003085 status = rw_t2t_soft_lock_tag();
3086 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003087 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003088
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003089 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003090}
3091
Ruchi Kandoi303fec12016-12-14 13:22:38 -08003092#endif /* (RW_NDEF_INCLUDED == TRUE) */