blob: f2877c0a08ad01cd95e2f7a02c0d0b0d269a8502 [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));
623 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits =
624 p_t2t->tlv_value[1];
625 count = p_t2t->tlv_value[1] / 8 +
626 ((p_t2t->tlv_value[1] % 8 != 0) ? 1 : 0);
627
628 /* Extract lockbytes info addressed by this Lock TLV */
629 xx = 0;
Ruchi Kandoi183352b2018-09-21 14:04:22 -0700630 if (count > RW_T2T_MAX_LOCK_BYTES) {
631 count = RW_T2T_MAX_LOCK_BYTES;
632 android_errorWriteLog(0x534e4554, "112161557");
633 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800634 while (xx < count) {
635 p_t2t->lockbyte[p_t2t->num_lockbytes].tlv_index =
636 p_t2t->num_lock_tlvs;
637 p_t2t->lockbyte[p_t2t->num_lockbytes].byte_index = xx;
638 p_t2t->lockbyte[p_t2t->num_lockbytes].b_lock_read = false;
639 xx++;
640 p_t2t->num_lockbytes++;
641 }
642 p_t2t->num_lock_tlvs++;
643 rw_t2t_update_attributes();
644 /* Next byte could be a different TLV */
645 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
646 }
647 } else {
648 /* If not looking for lock/ndef tlv, just skip this Lock TLV */
649 if (p_t2t->bytes_count == 0) {
650 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
651 }
652 }
653 break;
654
655 case TAG_MEM_CTRL_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800656 if (p_t2t->bytes_count > 0) {
657 p_t2t->bytes_count--;
658 } else {
659 LOG(ERROR) << StringPrintf("bytes_count underflow!");
660 android_errorWriteLog(0x534e4554, "120506143");
661 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800662 if ((tlvtype == TAG_MEM_CTRL_TLV) || (tlvtype == TAG_NDEF_TLV)) {
663 p_t2t->tlv_value[2 - p_t2t->bytes_count] = p_data[offset];
664 if (p_t2t->bytes_count == 0) {
665 if (p_t2t->num_mem_tlvs >= RW_T2T_MAX_MEM_TLVS) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700666 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800667 "rw_t2t_handle_tlv_detect_rsp - Maximum buffer allocated "
668 "for Memory tlv has reached");
669 failed = true;
670 } else {
671 /* Extract memory control tlv */
672 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
673 (p_t2t->tlv_value[0] >> 4) & 0x0F;
674 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
675 (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
676 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
677 p_t2t->tlv_value[0] & 0x0F;
678 p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
679 p_t2t->tlv_value[1];
680 p_t2t->num_mem_tlvs++;
681 rw_t2t_update_attributes();
682 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
683 }
684 }
685 } else {
686 if (p_t2t->bytes_count == 0) {
687 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
688 }
689 }
690 break;
691
692 case TAG_PROPRIETARY_TLV:
George Changb5f3ef42019-01-08 22:32:42 +0800693 if (p_t2t->bytes_count > 0) {
694 p_t2t->bytes_count--;
695 } else {
696 LOG(ERROR) << StringPrintf("bytes_count underflow!");
697 android_errorWriteLog(0x534e4554, "120506143");
698 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800699 if (tlvtype == TAG_PROPRIETARY_TLV) {
700 found = true;
701 p_t2t->prop_msg_len = len;
702 } else {
703 if (p_t2t->bytes_count == 0) {
704 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
705 }
706 }
707 break;
708 }
709 offset++;
710 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800711 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800712 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800713
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800714 p_t2t->work_offset += T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800715
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800716 event = rw_t2t_info_to_event(p_cmd_rsp_info);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800717
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800718 /* If not found and not failed, read next block and search tlv */
719 if (!found && !failed) {
720 if (p_t2t->work_offset >=
721 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR)) {
722 if (((tlvtype == TAG_LOCK_CTRL_TLV) && (p_t2t->num_lockbytes > 0)) ||
723 ((tlvtype == TAG_MEM_CTRL_TLV) && (p_t2t->num_mem_tlvs > 0))) {
724 found = true;
725 } else {
726 failed = true;
727 }
728 } else {
729 if (rw_t2t_read((uint16_t)((p_t2t->work_offset / T2T_BLOCK_LEN) +
730 T2T_FIRST_DATA_BLOCK)) != NFC_STATUS_OK)
731 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800732 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800733 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800734
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800735 if (failed || found) {
736 if (tlvtype == TAG_LOCK_CTRL_TLV) {
737 /* Incase no Lock control tlv is present then look for default dynamic
738 * lock bytes */
739 rw_t2t_extract_default_locks_info();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800740
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800741 /* Send command to read the dynamic lock bytes */
742 status = rw_t2t_read_locks();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800743
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800744 if (status != NFC_STATUS_CONTINUE) {
745 /* If unable to read a lock/all locks read, notify upper layer */
746 rw_t2t_update_lock_attributes();
747 rw_t2t_ntf_tlv_detect_complete(status);
748 }
749 } else if (tlvtype == TAG_NDEF_TLV) {
750 rw_t2t_extract_default_locks_info();
751
752 if (failed) {
753 rw_t2t_ntf_tlv_detect_complete(NFC_STATUS_FAILED);
754 } else {
755 /* NDEF present,Send command to read the dynamic lock bytes */
756 status = rw_t2t_read_locks();
757 if (status != NFC_STATUS_CONTINUE) {
758 /* If unable to read a lock/all locks read, notify upper layer */
759 rw_t2t_update_lock_attributes();
760 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800761 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800762 }
763 } else {
764 /* Notify Memory/ Proprietary tlv detect result */
765 status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
766 rw_t2t_ntf_tlv_detect_complete(status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800767 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800768 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800769}
770
771/*******************************************************************************
772**
773** Function rw_t2t_read_locks
774**
775** Description This function will send command to read next unread locks
776**
777** Returns NFC_STATUS_OK, if all locks are read successfully
778** NFC_STATUS_FAILED, if reading locks failed
779** NFC_STATUS_CONTINUE, if reading locks is in progress
780**
781*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800782tNFC_STATUS rw_t2t_read_locks(void) {
783 uint8_t num_locks = 0;
784 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
785 tNFC_STATUS status = NFC_STATUS_CONTINUE;
786 uint16_t offset;
787 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800788
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800789 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) ||
790 (p_t2t->skip_dyn_locks)) {
791 /* Skip reading dynamic lock bytes if CC is set as Read only or layer above
792 * instructs to skip */
793 while (num_locks < p_t2t->num_lockbytes) {
794 p_t2t->lockbyte[num_locks].lock_byte = 0x00;
795 p_t2t->lockbyte[num_locks].b_lock_read = true;
796 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800797 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800798 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800799
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800800 while (num_locks < p_t2t->num_lockbytes) {
801 if (p_t2t->lockbyte[num_locks].b_lock_read == false) {
802 /* Send Read command to read the first un read locks */
803 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
804 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800805
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800806 /* Read 16 bytes where this lock byte is present */
807 block = (uint16_t)(offset / T2T_BLOCK_LEN);
808 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800809
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800810 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_LOCKS;
811 /* send READ8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800812 status = rw_t2t_read((uint16_t)block);
813 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800814 /* Reading Locks */
815 status = NFC_STATUS_CONTINUE;
816 } else {
817 status = NFC_STATUS_FAILED;
818 }
819 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800820 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800821 num_locks++;
822 }
823 if (num_locks == p_t2t->num_lockbytes) {
824 /* All locks are read */
825 status = NFC_STATUS_OK;
826 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800827
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800828 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800829}
830
831/*******************************************************************************
832**
833** Function rw_t2t_extract_default_locks_info
834**
835** Description This function will prepare lockbytes information for default
836** locks present in the tag in the absence of lock control tlv.
837** Adding a virtual lock control tlv for these lock bytes for
838** easier manipulation.
839**
840** Returns None
841**
842*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800843void rw_t2t_extract_default_locks_info(void) {
844 uint8_t num_dynamic_lock_bits;
845 uint8_t num_dynamic_lock_bytes;
846 uint8_t xx;
847 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
848 const tT2T_INIT_TAG* p_ret;
849 uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800850
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800851 if ((p_t2t->num_lock_tlvs == 0) &&
852 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
853 /* No Lock control tlv is detected. Indicates lock bytes are present in
854 * default location */
855 /* Add a virtual Lock tlv to map this default lock location */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800856 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
857 if (p_ret != NULL) bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800858
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800859 num_dynamic_lock_bits =
860 ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
861 (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
862 bytes_locked_per_lock_bit;
863 num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
864 num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800865
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800866 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
867 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
868 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
869 p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
870 bytes_locked_per_lock_bit;
871 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 -0800872
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800873 /* Based on tag data size the number of locks present in the default
874 * location changes */
875 for (xx = 0; xx < num_dynamic_lock_bytes; xx++) {
876 p_t2t->lockbyte[xx].tlv_index = p_t2t->num_lock_tlvs;
877 p_t2t->lockbyte[xx].byte_index = xx;
878 p_t2t->lockbyte[xx].b_lock_read = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800879 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800880 p_t2t->num_lockbytes = num_dynamic_lock_bytes;
881 p_t2t->num_lock_tlvs = 1;
882 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800883}
884
885/*******************************************************************************
886**
887** Function rw_t2t_read_ndef_last_block
888**
889** Description This function will locate and read the last ndef block.
890** The last ndef block refers to the tag block where last byte
891** of new ndef message will reside. Also this function will
892** locate the offset of Terminator TLV based on the size of
893** new NDEF Message
894**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800895** Returns NCI_STATUS_OK, if able to locate last ndef block & read
896** started. Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800897**
898*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800899tNFC_STATUS rw_t2t_read_ndef_last_block(void) {
900 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
901 uint16_t header_len = (p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN)
902 ? T2T_LONG_NDEF_LEN_FIELD_LEN
903 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
904 uint16_t num_ndef_bytes;
905 uint16_t total_ndef_bytes;
906 uint16_t last_ndef_byte_offset;
907 uint16_t terminator_tlv_byte_index;
908 tNFC_STATUS status;
909 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800910
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800911 total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
912 num_ndef_bytes = 0;
913 last_ndef_byte_offset = p_t2t->ndef_header_offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800914
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800915 /* Locate NDEF final block based on the size of new NDEF Message */
916 while (num_ndef_bytes < total_ndef_bytes) {
917 if (rw_t2t_is_lock_res_byte((uint16_t)(last_ndef_byte_offset)) == false)
918 num_ndef_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800919
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800920 last_ndef_byte_offset++;
921 }
922 p_t2t->ndef_last_block_num =
923 (uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
924 block = p_t2t->ndef_last_block_num;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800925
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800926 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
927 /* Read NDEF last block before updating */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -0800928 status = rw_t2t_read(block);
929 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800930 if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
931 /* Locate Terminator TLV Block */
932 total_ndef_bytes++;
933 terminator_tlv_byte_index = last_ndef_byte_offset;
934
935 while (num_ndef_bytes < total_ndef_bytes) {
936 if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
937 false)
938 num_ndef_bytes++;
939
940 terminator_tlv_byte_index++;
941 }
942
943 p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
944 } else {
945 /* No space for Terminator TLV */
946 p_t2t->terminator_byte_index = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800947 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800948 }
949 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800950}
951
952/*******************************************************************************
953**
954** Function rw_t2t_read_terminator_tlv_block
955**
956** Description This function will read the block where terminator tlv will
957** be added later
958**
959** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
960**
961*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800962tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
963 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
964 tNFC_STATUS status;
965 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800966
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800967 /* Send read command to read base block (Block % 4==0) where this block is
968 * also read as part of 16 bytes */
969 block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
970 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800971
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800972 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
973 /* Read the block where Terminator TLV may be added later during NDEF Write
974 * operation */
975 status = rw_t2t_read(block);
976 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800977}
978
979/*******************************************************************************
980**
981** Function rw_t2t_read_ndef_next_block
982**
983** Description This function will read the tag block passed as argument
984**
985** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
986**
987*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800988tNFC_STATUS rw_t2t_read_ndef_next_block(uint16_t block) {
989 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
990 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800991
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800992 /* Send read command to read base block (Block % 4==0) where this block is
993 * also read as part of 16 bytes */
994 block -= block % T2T_READ_BLOCKS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800995
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800996 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK;
997 /* Read the block */
998 status = rw_t2t_read(block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800999
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001000 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001001}
1002
1003/*******************************************************************************
1004**
1005** Function rw_t2t_is_read_before_write_block
1006**
1007** Description This function will check if the block has to be read before
1008** writting to avoid over writting in to lock/reserved bytes
1009** present in the block.
1010** If no bytes in the block can be overwritten it moves in to
1011** next block and check. Finally it finds a block where part of
1012** ndef bytes can exist and check if the whole block can be
1013** updated or only part of block can be modified.
1014**
1015** Returns TRUE, if the block returned should be read before writting
1016** FALSE, if the block need not be read as it was already
1017** read or during NDEF write we may completely overwrite
1018** the block and there is no reserved or locked bytes in
1019** that block
1020**
1021*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001022static bool rw_t2t_is_read_before_write_block(uint16_t block,
1023 uint16_t* p_block_to_read) {
1024 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1025 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1026 uint8_t count;
1027 uint8_t index;
1028 uint16_t tag_size = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1029 bool read_before_write = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001030
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001031 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1032 /* First NDEF block is already read */
1033 read_before_write = false;
1034 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
1035 } else if (block == p_t2t->ndef_last_block_num) {
1036 /* Last NDEF block is already read */
1037 read_before_write = false;
1038 memcpy(p_t2t->ndef_read_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1039 } else if (block == p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) {
1040 /* Terminator tlv block is already read */
1041 read_before_write = false;
1042 memcpy(p_t2t->ndef_read_block, p_t2t->terminator_tlv_block, T2T_BLOCK_SIZE);
1043 } else {
1044 count = 0;
1045 while (block < tag_size) {
1046 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001047
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001048 while (index < T2T_BLOCK_SIZE) {
1049 /* check if it is a reserved or locked byte */
1050 if (rw_t2t_is_lock_res_byte(
1051 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1052 count++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001053 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001054 index++;
1055 }
1056 if (count == T2T_BLOCK_SIZE) {
1057 /* All the bytes in the block are free to NDEF write */
1058 read_before_write = false;
1059 break;
1060 } else if (count == 0) {
1061 /* The complete block is not free for NDEF write */
1062 index = 0;
1063 block++;
1064 } else {
1065 /* The block has reseved byte (s) or locked byte (s) or both */
1066 read_before_write = true;
1067 break;
1068 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001069 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001070 }
1071 /* Return the block to read next before NDEF write */
1072 *p_block_to_read = block;
1073 return read_before_write;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001074}
1075
1076/*******************************************************************************
1077**
1078** Function rw_t2t_write_ndef_first_block
1079**
1080** Description This function will write the first NDEF block with Length
1081** field reset to zero.
1082** Also after writting NDEF this function may be called to
1083** update new NDEF length
1084**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001085** Returns NCI_STATUS_OK, if write was started.
1086** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001087**
1088*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001089tNFC_STATUS rw_t2t_write_ndef_first_block(uint16_t msg_len, bool b_update_len) {
1090 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1091 uint8_t new_lengthfield_len;
1092 uint8_t write_block[4];
1093 uint8_t block;
1094 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1095 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1096 tNFC_STATUS status;
1097 uint8_t length_field[3];
1098 uint8_t index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001099
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001100 p_t2t->work_offset = 0;
1101 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1102 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1103 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1104 if (new_lengthfield_len == 3) {
1105 /* New NDEF is Long NDEF */
1106 if (msg_len == 0) {
1107 /* Clear NDEF length field */
1108 length_field[0] = 0x00;
1109 length_field[1] = 0x00;
1110 length_field[2] = 0x00;
1111 } else {
1112 /* Update NDEF length field with new NDEF Msg len */
1113 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1114 length_field[1] = (uint8_t)(msg_len >> 8);
1115 length_field[2] = (uint8_t)(msg_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001116 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001117 } else {
1118 /* New NDEF is Short NDEF */
1119 length_field[0] = (uint8_t)(msg_len);
1120 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001121
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001122 /* updating ndef_first_block with new ndef message */
1123 memcpy(write_block, p_t2t->ndef_first_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001124
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001125 index = p_t2t->ndef_header_offset % T2T_BLOCK_SIZE;
1126 block = (uint8_t)(p_t2t->ndef_header_offset / T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001127
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001128 while (p_t2t->work_offset == 0 && block < total_blocks) {
1129 /* update length field */
1130 while (index < T2T_BLOCK_SIZE &&
1131 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1132 if (rw_t2t_is_lock_res_byte(
1133 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1134 write_block[index] = length_field[p_t2t->work_offset];
1135 p_t2t->work_offset++;
1136 }
1137 index++;
1138 if (p_t2t->work_offset == new_lengthfield_len) {
1139 break;
1140 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001141 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001142 /* If more space in this block then add ndef message */
1143 while (index < T2T_BLOCK_SIZE &&
1144 p_t2t->work_offset <
1145 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1146 if (rw_t2t_is_lock_res_byte(
1147 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1148 write_block[index] =
1149 p_t2t->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1150 p_t2t->work_offset++;
1151 }
1152 index++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001153 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001154 if (p_t2t->work_offset == 0) {
1155 /* If no bytes are written move to next block */
1156 index = 0;
1157 block++;
1158 if (block == p_t2t->ndef_last_block_num) {
1159 memcpy(write_block, p_t2t->ndef_last_block, T2T_BLOCK_SIZE);
1160 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001161 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001162 }
1163 if (p_t2t->work_offset == 0) {
1164 status = NFC_STATUS_FAILED;
1165 } else {
1166 rw_t2t_update_cb(block, write_block, b_update_len);
1167 /* Update the identified block with newly prepared data */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001168 status = rw_t2t_write(block, write_block);
1169 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001170 p_t2t->b_read_data = false;
1171 }
1172 }
1173 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001174}
1175
1176/*******************************************************************************
1177**
1178** Function rw_t2t_write_ndef_next_block
1179**
1180** Description This function can be called to write an NDEF message block
1181**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001182** Returns NCI_STATUS_OK, if write was started.
1183** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001184**
1185*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001186tNFC_STATUS rw_t2t_write_ndef_next_block(uint16_t block, uint16_t msg_len,
1187 bool b_update_len) {
1188 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1189 uint8_t new_lengthfield_len;
1190 uint8_t write_block[4];
1191 uint8_t* p_cc = &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE];
1192 uint16_t total_blocks = p_cc[2] * 2 + T2T_FIRST_DATA_BLOCK;
1193 uint16_t initial_offset;
1194 uint8_t length_field[3];
1195 uint8_t index;
1196 tNFC_STATUS status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001197
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001198 /* Write NDEF Message */
1199 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1200 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1201 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001202
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001203 index = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001204
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001205 memcpy(write_block, p_t2t->ndef_read_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001206
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001207 if (p_t2t->work_offset >= new_lengthfield_len) {
1208 /* Length field is updated, write ndef message field */
1209 initial_offset = p_t2t->work_offset;
1210 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1211 while (index < T2T_BLOCK_SIZE &&
1212 p_t2t->work_offset <
1213 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1214 if (rw_t2t_is_lock_res_byte(
1215 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1216 write_block[index] =
1217 p_t2t
1218 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1219 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001220 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001221 index++;
1222 }
1223 if (p_t2t->work_offset == initial_offset) {
1224 index = 0;
1225 block++;
1226 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001227 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001228 } else {
1229 /* Complete writting Length field and then write ndef message */
1230 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1231 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1232 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
1233 if (new_lengthfield_len == 3) {
1234 /* New NDEF is Long NDEF */
1235 if (msg_len == 0) {
1236 length_field[0] = 0x00;
1237 length_field[1] = 0x00;
1238 length_field[2] = 0x00;
1239 } else {
1240 length_field[0] = T2T_LONG_NDEF_LEN_FIELD_BYTE0;
1241 length_field[1] = (uint8_t)(msg_len >> 8);
1242 length_field[2] = (uint8_t)(msg_len);
1243 }
1244 } else {
1245 /* New NDEF is short NDEF */
1246 length_field[0] = (uint8_t)(msg_len);
1247 }
1248 initial_offset = p_t2t->work_offset;
1249 while (p_t2t->work_offset == initial_offset && block < total_blocks) {
1250 /* Update length field */
1251 while (index < T2T_BLOCK_SIZE &&
1252 p_t2t->work_offset < p_t2t->new_ndef_msg_len) {
1253 if (rw_t2t_is_lock_res_byte(
1254 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1255 write_block[index] = length_field[p_t2t->work_offset];
1256 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001257 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001258 index++;
1259 if (p_t2t->work_offset == new_lengthfield_len) {
1260 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001261 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001262 }
1263 /* Update ndef message field */
1264 while (index < T2T_BLOCK_SIZE &&
1265 p_t2t->work_offset <
1266 (p_t2t->new_ndef_msg_len + new_lengthfield_len)) {
1267 if (rw_t2t_is_lock_res_byte(
1268 (uint16_t)((block * T2T_BLOCK_SIZE) + index)) == false) {
1269 write_block[index] =
1270 p_t2t
1271 ->p_new_ndef_buffer[p_t2t->work_offset - new_lengthfield_len];
1272 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001273 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001274 index++;
1275 }
1276 if (p_t2t->work_offset == initial_offset) {
1277 index = 0;
1278 block++;
1279 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001280 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001281 }
1282 if (p_t2t->work_offset == initial_offset) {
1283 status = NFC_STATUS_FAILED;
1284 } else {
1285 rw_t2t_update_cb(block, write_block, b_update_len);
1286 /* Write the NDEF Block */
1287 status = rw_t2t_write(block, write_block);
1288 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001289
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001290 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001291}
1292
1293/*******************************************************************************
1294**
1295** Function rw_t2t_update_cb
1296**
1297** Description This function can be called to write an NDEF message block
1298**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001299** Returns NCI_STATUS_OK, if write was started.
1300** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001301**
1302*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001303static void rw_t2t_update_cb(uint16_t block, uint8_t* p_write_block,
1304 bool b_update_len) {
1305 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1306 uint8_t new_lengthfield_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001307
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001308 /* Write NDEF Message */
1309 new_lengthfield_len = p_t2t->new_ndef_msg_len >= T2T_LONG_NDEF_MIN_LEN
1310 ? T2T_LONG_NDEF_LEN_FIELD_LEN
1311 : T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001312
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001313 if (block == p_t2t->ndef_header_offset / T2T_BLOCK_SIZE) {
1314 /* Update ndef first block if the 'block' points to ndef first block */
1315 memcpy(p_t2t->ndef_first_block, p_write_block, T2T_BLOCK_SIZE);
1316 }
1317 if (p_t2t->terminator_byte_index / T2T_BLOCK_SIZE == block) {
1318 /* Update terminator block if the 'block' points to terminator tlv block */
1319 memcpy(p_t2t->terminator_tlv_block, p_write_block, T2T_BLOCK_LEN);
1320 }
1321 if (b_update_len == false) {
1322 if (block == p_t2t->ndef_last_block_num) {
1323 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK;
1324 p_t2t->work_offset = 0;
1325 /* Update ndef final block if the 'block' points to ndef final block */
1326 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
1327 } else {
1328 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001329 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001330 } else {
1331 if (block == p_t2t->ndef_last_block_num) {
1332 /* Update the backup of Ndef final block TLV block */
1333 memcpy(p_t2t->ndef_last_block, p_write_block, T2T_BLOCK_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001334 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001335
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001336 if (p_t2t->work_offset >= new_lengthfield_len) {
1337 if (p_t2t->terminator_byte_index != 0) {
1338 /* Add Terminator TLV as part of NDEF Write operation */
1339 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK;
1340 } else {
1341 /* Skip adding Terminator TLV */
1342 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
1343 }
1344 } else {
1345 /* Part of NDEF Message Len should be added in the next block */
1346 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001347 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001348 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001349}
1350
1351/*******************************************************************************
1352**
1353** Function rw_t2t_get_ndef_flags
1354**
1355** Description Prepare NDEF Flags
1356**
1357** Returns NDEF Flag value
1358**
1359*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001360static uint8_t rw_t2t_get_ndef_flags(void) {
1361 uint8_t flags = 0;
1362 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1363 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001364
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001365 flags |= RW_NDEF_FL_SUPPORTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001366
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001367 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC) ||
1368 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == 0))
1369 flags |= RW_NDEF_FL_FORMATABLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001370
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001371 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO)
1372 flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001373
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001374 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1375 (p_ret->b_otp)) {
1376 /* Set otp flag */
1377 flags |= RW_NDEF_FL_OTP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001378
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001379 /* Set Read only flag if otp tag already has NDEF Message */
1380 if (p_t2t->ndef_msg_len) flags |= RW_NDEF_FL_READ_ONLY;
1381 }
1382 return flags;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001383}
1384
1385/*******************************************************************************
1386**
1387** Function rw_t2t_get_ndef_max_size
1388**
1389** Description Calculate maximum size of NDEF message that can be written
1390** on to the tag
1391**
1392** Returns Maximum size of NDEF Message
1393**
1394*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001395static uint16_t rw_t2t_get_ndef_max_size(void) {
1396 uint16_t offset;
1397 uint8_t xx;
1398 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1399 uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
1400 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
1401 p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001402
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001403 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
1404 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001405
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001406 offset = p_t2t->ndef_msg_offset;
1407 p_t2t->max_ndef_msg_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001408
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001409 if ((tag_size < T2T_STATIC_SIZE) ||
1410 (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
1411 ((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
1412 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
1413 /* Tag not formated, assume static tag */
1414 p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
1415 T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001416 return p_t2t->max_ndef_msg_len;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001417 }
1418
1419 /* Starting from NDEF Message offset find the first locked data byte */
1420 while (offset < tag_size) {
1421 if (rw_t2t_is_lock_res_byte((uint16_t)offset) == false) {
1422 if (rw_t2t_is_read_only_byte((uint16_t)offset) == true) break;
1423 p_t2t->max_ndef_msg_len++;
1424 }
1425 offset++;
1426 }
1427 /* NDEF Length field length changes based on NDEF size */
1428 if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
1429 ((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
1430 T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
1431 p_t2t->max_ndef_msg_len -=
1432 (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
1433 ? 1
1434 : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
1435 }
1436 return p_t2t->max_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001437}
1438
1439/*******************************************************************************
1440**
1441** Function rw_t2t_add_terminator_tlv
1442**
1443** Description This function will add terminator TLV after NDEF Message
1444**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001445** Returns NCI_STATUS_OK, if write was started.
1446** Otherwise, error status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001447**
1448*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001449tNFC_STATUS rw_t2t_add_terminator_tlv(void) {
1450 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1451 tNFC_STATUS status;
1452 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001453
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001454 /* Add Terminator TLV after NDEF Message */
1455 p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
1456 TAG_TERMINATOR_TLV;
1457 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001458
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001459 block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
1460 status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001461
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001462 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001463}
1464
1465/*******************************************************************************
1466**
1467** Function rw_t2t_handle_ndef_read_rsp
1468**
1469** Description This function handles reading an NDEF message.
1470**
1471** Returns none
1472**
1473*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001474static void rw_t2t_handle_ndef_read_rsp(uint8_t* p_data) {
1475 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1476 tRW_READ_DATA evt_data;
1477 uint16_t len;
1478 uint16_t offset;
1479 bool failed = false;
1480 bool done = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001481
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001482 /* On the first read, adjust for any partial block offset */
1483 offset = 0;
1484 len = T2T_READ_DATA_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001485
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001486 if (p_t2t->work_offset == 0) {
1487 /* The Ndef Message offset may be present in the read 16 bytes */
1488 offset = (p_t2t->ndef_msg_offset - (p_t2t->block_read * T2T_BLOCK_SIZE));
1489 }
1490
1491 /* Skip all reserved and lock bytes */
1492 while ((offset < len) && (p_t2t->work_offset < p_t2t->ndef_msg_len))
1493
1494 {
1495 if (rw_t2t_is_lock_res_byte(
1496 (uint16_t)(offset + p_t2t->block_read * T2T_BLOCK_LEN)) == false) {
1497 /* Collect the NDEF Message */
1498 p_t2t->p_ndef_buffer[p_t2t->work_offset] = p_data[offset];
1499 p_t2t->work_offset++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001500 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001501 offset++;
1502 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001503
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001504 if (p_t2t->work_offset >= p_t2t->ndef_msg_len) {
1505 done = true;
1506 p_t2t->ndef_status = T2T_NDEF_READ;
1507 } else {
1508 /* Read next 4 blocks */
1509 if (rw_t2t_read((uint16_t)(p_t2t->block_read + T2T_READ_BLOCKS)) !=
1510 NFC_STATUS_OK)
1511 failed = true;
1512 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001513
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001514 if (failed || done) {
1515 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1516 evt_data.p_data = NULL;
1517 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001518 tRW_DATA rw_data;
1519 rw_data.data = evt_data;
1520 (*rw_cb.p_cback)(RW_T2T_NDEF_READ_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001521 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001522}
1523
1524/*******************************************************************************
1525**
1526** Function rw_t2t_handle_ndef_write_rsp
1527**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001528** Description Handle response received to reading (or part of) NDEF
1529** message.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001530**
1531** Returns none
1532**
1533*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001534static void rw_t2t_handle_ndef_write_rsp(uint8_t* p_data) {
1535 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1536 tRW_READ_DATA evt_data;
1537 bool failed = false;
1538 bool done = false;
1539 uint16_t block;
1540 uint8_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001541
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001542 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001543 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1544
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001545 /* Backup the read NDEF first block */
1546 memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
1547 /* Read ndef final block */
1548 if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
1549 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001550
1551 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1552
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001553 offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
1554 T2T_BLOCK_SIZE;
1555 /* Backup the read NDEF final block */
1556 memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
1557 if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
1558 p_t2t->ndef_last_block_num) {
1559 /* If Terminator TLV will reside on the NDEF Final block */
1560 memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
1561 T2T_BLOCK_LEN);
1562 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1563 failed = true;
1564 } else if (p_t2t->terminator_byte_index != 0) {
1565 /* If there is space for Terminator TLV and if it will reside outside
1566 * NDEF Final block */
1567 if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
1568 } else {
1569 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1570 failed = true;
1571 }
1572 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001573
1574 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1575
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001576 offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
1577 p_t2t->block_read) *
1578 T2T_BLOCK_SIZE);
1579 /* Backup the read Terminator TLV block */
1580 memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001581
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001582 /* Write the first block for new NDEF Message */
1583 if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
1584 failed = true;
1585 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001586
1587 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1588
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001589 offset = (uint8_t)(p_t2t->ndef_read_block_num - p_t2t->block_read) *
1590 T2T_BLOCK_SIZE;
1591 /* Backup read block */
1592 memcpy(p_t2t->ndef_read_block, &p_data[offset], T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001593
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001594 /* Update the block with new NDEF Message */
1595 if (rw_t2t_write_ndef_next_block(p_t2t->ndef_read_block_num, 0x0000,
1596 false) != NFC_STATUS_OK)
1597 failed = true;
1598 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001599
1600 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1601 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001602 if (rw_t2t_is_read_before_write_block(
1603 (uint16_t)(p_t2t->block_written + 1), &block) == true) {
1604 p_t2t->ndef_read_block_num = block;
1605 /* If only part of the block is going to be updated read the block to
1606 retain previous data for
1607 unchanged part of the block */
1608 if (rw_t2t_read_ndef_next_block(block) != NFC_STATUS_OK) failed = true;
1609 } else {
1610 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK) {
1611 /* Directly write the block with new NDEF contents as whole block is
1612 * going to be updated */
1613 if (rw_t2t_write_ndef_next_block(block, p_t2t->new_ndef_msg_len,
1614 true) != NFC_STATUS_OK)
1615 failed = true;
1616 } else {
1617 /* Directly write the block with new NDEF contents as whole block is
1618 * going to be updated */
1619 if (rw_t2t_write_ndef_next_block(block, 0x0000, false) !=
1620 NFC_STATUS_OK)
1621 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001622 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001623 }
1624 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001625
1626 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001627 /* Write the next block for new NDEF Message */
1628 p_t2t->ndef_write_block = p_t2t->ndef_header_offset / T2T_BLOCK_SIZE;
1629 if (rw_t2t_is_read_before_write_block((uint16_t)(p_t2t->ndef_write_block),
1630 &block) == true) {
1631 /* If only part of the block is going to be updated read the block to
1632 retain previous data for
1633 part of the block thats not going to be changed */
1634 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK;
1635 if (rw_t2t_read(block) != NFC_STATUS_OK) failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001636
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001637 } else {
1638 /* Update NDEF Message Length in the Tag */
1639 if (rw_t2t_write_ndef_first_block(p_t2t->new_ndef_msg_len, true) !=
1640 NFC_STATUS_OK)
1641 failed = true;
1642 }
1643 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001644
1645 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001646 /* Backup read block */
1647 memcpy(p_t2t->ndef_read_block, p_data, T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001648
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001649 /* Update the block with new NDEF Message */
1650 if (rw_t2t_write_ndef_next_block(p_t2t->block_read,
1651 p_t2t->new_ndef_msg_len,
1652 true) == NFC_STATUS_OK)
1653 p_t2t->ndef_write_block = p_t2t->block_read + 1;
1654 else
1655 failed = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001656
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001657 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001658
1659 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001660 if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
1661 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001662
1663 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001664 done = true;
1665 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001666
1667 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001668 break;
1669 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001670
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001671 if (failed || done) {
1672 evt_data.p_data = NULL;
1673 /* NDEF WRITE Operation is done, inform up the stack */
1674 evt_data.status = failed ? NFC_STATUS_FAILED : NFC_STATUS_OK;
1675 if (done) {
1676 if ((p_t2t->ndef_msg_len >= 0x00FF) &&
1677 (p_t2t->new_ndef_msg_len < 0x00FF)) {
1678 p_t2t->ndef_msg_offset -= 2;
1679 } else if ((p_t2t->new_ndef_msg_len >= 0x00FF) &&
1680 (p_t2t->ndef_msg_len < 0x00FF)) {
1681 p_t2t->ndef_msg_offset += 2;
1682 }
1683 p_t2t->ndef_msg_len = p_t2t->new_ndef_msg_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001684 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001685 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001686 tRW_DATA rw_data;
1687 rw_data.data = evt_data;
1688 (*rw_cb.p_cback)(RW_T2T_NDEF_WRITE_EVT, &rw_data);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001689 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001690}
1691
1692/*******************************************************************************
1693**
1694** Function rw_t2t_get_tag_size
1695**
1696** Description This function calculates tag data area size from data read
1697** from block with version number
1698**
1699** Returns TMS of the tag
1700**
1701*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001702static uint8_t rw_t2t_get_tag_size(uint8_t* p_data) {
1703 uint16_t LchunkSize = 0;
1704 uint16_t Num_LChuncks = 0;
1705 uint16_t tms = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001706
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001707 LchunkSize = (uint16_t)p_data[2] << 8 | p_data[3];
1708 Num_LChuncks = (uint16_t)p_data[4] << 8 | p_data[5];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001709
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001710 tms = (uint16_t)(LchunkSize * Num_LChuncks);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001711
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001712 tms += (T2T_STATIC_SIZE - T2T_HEADER_SIZE);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001713
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001714 tms /= 0x08;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001715
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001716 return (uint8_t)tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001717}
1718
1719/*******************************************************************************
1720**
1721** Function rw_t2t_handle_config_tag_readonly
1722**
1723** Description This function handles configure type 2 tag as read only
1724**
1725** Returns none
1726**
1727*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001728static void rw_t2t_handle_config_tag_readonly(uint8_t* p_data) {
1729 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1730 tNFC_STATUS status = NFC_STATUS_FAILED;
1731 bool b_notify = false;
1732 uint8_t write_block[T2T_BLOCK_SIZE];
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001733 bool b_pending = false;
1734 uint8_t read_lock = 0;
1735 uint8_t num_locks = 0;
1736 uint16_t offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001737
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001738 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001739 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1740
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001741 /* First soft lock the tag */
1742 rw_t2t_soft_lock_tag();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001743
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001744 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001745
1746 case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
1747
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001748 /* Successfully soft locked! Update Tag header for future reference */
1749 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] = T2T_CC3_RWA_RO;
1750 if (!p_t2t->b_hard_lock) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001751 /* Tag configuration complete */
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001752 status = NFC_STATUS_OK;
Ruchi Kandoi4a179642017-01-04 10:04:48 -08001753 b_notify = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001754 break;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001755 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001756
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001757 /* Coverity: [FALSE-POSITIVE error] intended fall through */
1758 /* Missing break statement between cases in switch statement */
1759 /* fall through */
1760 case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001761
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001762 num_locks = 0;
1763
1764 while (num_locks < p_t2t->num_lockbytes) {
1765 if (p_t2t->lockbyte[num_locks].lock_status ==
1766 RW_T2T_LOCK_UPDATE_INITIATED) {
1767 /* Update control block as one or more dynamic lock byte (s) are set
1768 */
1769 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_UPDATED;
1770 }
1771 if (!b_pending &&
1772 p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
1773 /* One or more dynamic lock bits are not set */
1774 b_pending = true;
1775 read_lock = num_locks;
1776 }
1777 num_locks++;
1778 }
1779
1780 if (b_pending) {
1781 /* Read the block where dynamic lock bits are present to avoid writing
1782 * to NDEF bytes in the same block */
1783 offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
1784 p_t2t->lockbyte[read_lock].byte_index;
1785 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
1786 status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
1787 } else {
1788 /* Now set Static lock bits as no more dynamic lock bits to set */
1789
1790 /* Copy the internal bytes */
1791 memcpy(write_block,
1792 &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
1793 T2T_INTERNAL_BYTES_LEN);
1794 /* Set all Static lock bits */
1795 write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
1796 write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
1797 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
1798 status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
1799 }
1800 break;
1801
1802 case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
1803 /* Now set the dynamic lock bits present in the block read now */
1804 status = rw_t2t_set_dynamic_lock_bits(p_data);
1805 break;
1806
1807 case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
1808 /* Tag configuration complete */
1809 status = NFC_STATUS_OK;
1810 b_notify = true;
1811 break;
1812 }
1813
1814 if (status != NFC_STATUS_OK || b_notify) {
1815 /* Notify upper layer the result of Configuring Tag as Read only */
Myles Watson1361d522017-09-26 13:39:54 -07001816 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001817 evt.status = status;
1818 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001819 (*rw_cb.p_cback)(RW_T2T_SET_TAG_RO_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001820 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001821}
1822
1823/*******************************************************************************
1824**
1825** Function rw_t2t_handle_format_tag_rsp
1826**
1827** Description This function handles formating a type 2 tag
1828**
1829** Returns none
1830**
1831*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001832static void rw_t2t_handle_format_tag_rsp(uint8_t* p_data) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001833 uint8_t* p;
1834 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1835 tNFC_STATUS status = NFC_STATUS_FAILED;
1836 uint16_t version_no;
1837 const tT2T_INIT_TAG* p_ret;
1838 uint8_t tms;
1839 uint8_t next_block = T2T_FIRST_DATA_BLOCK + 1;
1840 uint16_t addr, locked_area;
1841 bool b_notify = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001842
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001843 p = p_t2t->ndef_final_block;
1844 UINT8_TO_BE_STREAM(p, p_t2t->tlv_value[2]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001845
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001846 switch (p_t2t->substate) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001847 case RW_T2T_SUBSTATE_WAIT_READ_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001848 /* Start format operation */
1849 status = rw_t2t_format_tag();
1850 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001851
1852 case RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO:
1853
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001854 memcpy(p_t2t->tag_data, p_data, T2T_READ_DATA_LEN);
1855 p_t2t->b_read_data = true;
1856 version_no = (uint16_t)p_data[0] << 8 | p_data[1];
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001857 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no);
1858 if (p_ret != NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001859 /* Valid Version Number */
1860 if (p_ret->b_calc_cc) /* Calculate tag size from Version Information */
1861 tms = rw_t2t_get_tag_size(p_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001862
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001863 else
1864 /* Tag size from Look up table */
1865 tms = p_ret->tms;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001866
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001867 /* Set CC with the Tag size from look up table or from calculated value
1868 */
1869 status = rw_t2t_set_cc(tms);
1870 }
1871 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001872
1873 case RW_T2T_SUBSTATE_WAIT_SET_CC:
1874
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001875 version_no = (uint16_t)p_t2t->tag_data[0] << 8 | p_t2t->tag_data[1];
1876 if ((version_no == 0) ||
1877 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], true, version_no)) ==
1878 NULL) ||
1879 (!p_ret->b_multi_version) || (!p_ret->b_calc_cc)) {
1880 /* Currently Formating a non blank tag or a blank tag with manufacturer
1881 * has only one variant of tag. Set Null NDEF TLV and complete Format
1882 * Operation */
1883 next_block = T2T_FIRST_DATA_BLOCK;
1884 p = p_t2t->ndef_final_block;
1885 } else {
1886 addr = (uint16_t)(
1887 ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1888 ((uint16_t)p_t2t->tag_data[4] << 8 | p_t2t->tag_data[5]) +
1889 T2T_STATIC_SIZE);
1890 locked_area = ((uint16_t)p_t2t->tag_data[2] << 8 | p_t2t->tag_data[3]) *
1891 ((uint16_t)p_t2t->tag_data[6]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001892
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001893 status = rw_t2t_set_lock_tlv(addr, p_t2t->tag_data[7], locked_area);
1894 if (status == NFC_STATUS_REJECTED) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001895 /* Cannot calculate Lock TLV. Set Null NDEF TLV and complete Format
1896 * Operation */
1897 next_block = T2T_FIRST_DATA_BLOCK;
1898 p = p_t2t->ndef_final_block;
1899 } else
1900 break;
1901 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001902
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001903 /* falls through */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001904 case RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV:
1905
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001906 /* Prepare NULL NDEF TLV, TERMINATOR_TLV */
1907 UINT8_TO_BE_STREAM(p, TAG_NDEF_TLV);
1908 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001909
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001910 if (((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
1911 (!p_ret->b_otp)) {
1912 UINT8_TO_BE_STREAM(p, TAG_TERMINATOR_TLV);
1913 } else
1914 UINT8_TO_BE_STREAM(p, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001915
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001916 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF;
1917 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08001918 status = rw_t2t_write(next_block, p_t2t->ndef_final_block);
1919 if (status == NFC_STATUS_OK) p_t2t->b_read_data = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001920 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001921
1922 case RW_T2T_SUBSTATE_WAIT_SET_NULL_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001923 /* Tag Formated successfully */
1924 status = NFC_STATUS_OK;
1925 b_notify = true;
1926 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001927
1928 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001929 break;
1930 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001931
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001932 if (status != NFC_STATUS_OK || b_notify) {
1933 /* Notify upper layer the result of Format op */
Myles Watson1361d522017-09-26 13:39:54 -07001934 tRW_DATA evt;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001935 evt.status = status;
1936 rw_t2t_handle_op_complete();
Myles Watson1361d522017-09-26 13:39:54 -07001937 (*rw_cb.p_cback)(RW_T2T_FORMAT_CPLT_EVT, &evt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001938 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001939}
1940
1941/*******************************************************************************
1942**
1943** Function rw_t2t_update_attributes
1944**
1945** Description This function will update attribute for the current segment
1946** based on lock and reserved bytes
1947**
1948** Returns None
1949**
1950*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001951static void rw_t2t_update_attributes(void) {
1952 uint8_t count = 0;
1953 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
1954 uint16_t lower_offset;
1955 uint16_t upper_offset;
1956 uint16_t offset;
1957 uint8_t num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001958
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001959 /* Prepare attr for the current segment */
1960 memset(p_t2t->attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001961
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001962 /* calculate offset where the current segment starts in the tag */
1963 lower_offset = p_t2t->segment * RW_T2T_SEGMENT_BYTES;
1964 /* calculate offset where the current segment ends in the tag */
1965 upper_offset = (p_t2t->segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001966
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001967 /* check offset of lock bytes in the tag and update p_t2t->attr
1968 * for every lock byte that is present in the current segment */
1969 count = 0;
1970 while (count < p_t2t->num_lockbytes) {
1971 offset = p_t2t->lock_tlv[p_t2t->lockbyte[count].tlv_index].offset +
1972 p_t2t->lockbyte[count].byte_index;
1973 if (offset >= lower_offset && offset < upper_offset) {
1974 /* Calculate offset in the current segment as p_t2t->attr is prepared for
1975 * one segment only */
1976 offset %= RW_T2T_SEGMENT_BYTES;
1977 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
1978 * lock/reserved byte or not
1979 * So, each array element in p_t2t->attr covers two blocks in the tag as
1980 * T2 block size is 4 and array element size is 8
1981 * Set the corresponding bit in attr to indicate - reserved byte */
1982 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
1983 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001984 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001985 count++;
1986 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001987
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001988 /* Search reserved bytes identified by all memory tlvs present in the tag */
1989 count = 0;
1990 while (count < p_t2t->num_mem_tlvs) {
1991 /* check the offset of reserved bytes in the tag and update p_t2t->attr
1992 * for every reserved byte that is present in the current segment */
1993 num_bytes = 0;
1994 while (num_bytes < p_t2t->mem_tlv[count].num_bytes) {
1995 offset = p_t2t->mem_tlv[count].offset + num_bytes;
1996 if (offset >= lower_offset && offset < upper_offset) {
1997 /* Let offset represents offset in the current segment as p_t2t->attr is
1998 * prepared for one segment only */
1999 offset %= RW_T2T_SEGMENT_BYTES;
2000 /* Every bit in p_t2t->attr indicates one byte of the tag is either a
2001 * lock/reserved byte or not
2002 * So, each array element in p_t2t->attr covers two blocks in the tag as
2003 * T2 block size is 4 and array element size is 8
2004 * Set the corresponding bit in attr to indicate - reserved byte */
2005 p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
2006 rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
2007 }
2008 num_bytes++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002009 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002010 count++;
2011 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002012}
2013
2014/*******************************************************************************
2015**
2016** Function rw_t2t_get_lock_bits_for_segment
2017**
2018** Description This function returns the offset of lock bits associated for
2019** the specified segment
2020**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002021** Parameters: segment: The segment number to which lock bits are
2022** associated
2023** p_start_byte: The offset of lock byte that contains the
2024** first lock bit for the segment
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002025** p_start_bit: The offset of the lock bit in the lock byte
2026**
2027** p_end_byte: The offset of the last bit associcated to the
2028** segment
2029**
2030** Returns Total number of lock bits assigned to the specified segment
2031**
2032*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002033static uint8_t rw_t2t_get_lock_bits_for_segment(uint8_t segment,
2034 uint8_t* p_start_byte,
2035 uint8_t* p_start_bit,
2036 uint8_t* p_end_byte) {
2037 uint8_t total_bits = 0;
2038 uint16_t byte_count = 0;
2039 uint16_t lower_offset, upper_offset;
2040 uint8_t num_dynamic_locks = 0;
2041 uint8_t bit_count = 0;
2042 uint8_t bytes_locked_per_bit;
2043 uint8_t num_bits;
2044 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2045 bool b_all_bits_are_locks = true;
2046 uint16_t tag_size;
2047 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002048
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002049 tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
2050 (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_SIZE) + p_t2t->num_lockbytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002051
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002052 for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
2053 tag_size += p_t2t->mem_tlv[xx].num_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002054
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002055 lower_offset = segment * RW_T2T_SEGMENT_BYTES;
2056 if (segment == 0) {
2057 lower_offset += T2T_STATIC_SIZE;
2058 }
2059 upper_offset = (segment + 1) * RW_T2T_SEGMENT_BYTES;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002060
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002061 byte_count = T2T_STATIC_SIZE;
2062 if (tag_size < upper_offset) {
2063 upper_offset = tag_size;
2064 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002065
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002066 *p_start_byte = num_dynamic_locks;
2067 *p_start_bit = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002068
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002069 while ((byte_count <= lower_offset) &&
2070 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2071 bytes_locked_per_bit =
2072 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2073 .bytes_locked_per_bit;
2074 /* Number of bits in the current lock byte */
2075 b_all_bits_are_locks =
2076 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2077 TAG_BITS_PER_BYTE <=
2078 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2079 .num_bits);
2080 num_bits =
2081 b_all_bits_are_locks
2082 ? TAG_BITS_PER_BYTE
2083 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2084 .num_bits %
2085 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002086
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002087 if (((bytes_locked_per_bit * num_bits) + byte_count) <= lower_offset) {
2088 /* Skip this lock byte as it covers different segment */
2089 byte_count += bytes_locked_per_bit * num_bits;
2090 num_dynamic_locks++;
2091 } else {
2092 bit_count = 0;
2093 while (bit_count < num_bits) {
2094 byte_count += bytes_locked_per_bit;
2095 if (byte_count > lower_offset) {
2096 /* First lock bit that is used to lock this segment */
2097 *p_start_byte = num_dynamic_locks;
2098 *p_end_byte = num_dynamic_locks;
2099 *p_start_bit = bit_count;
2100 bit_count++;
2101 total_bits = 1;
2102 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002103 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002104 bit_count++;
2105 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002106 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002107 }
2108 if (num_dynamic_locks == p_t2t->num_lockbytes) {
2109 return 0;
2110 }
2111 while ((byte_count < upper_offset) &&
2112 (num_dynamic_locks < p_t2t->num_lockbytes)) {
2113 bytes_locked_per_bit =
2114 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2115 .bytes_locked_per_bit;
2116 /* Number of bits in the current lock byte */
2117 b_all_bits_are_locks =
2118 ((p_t2t->lockbyte[num_dynamic_locks].byte_index + 1) *
2119 TAG_BITS_PER_BYTE <=
2120 p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2121 .num_bits);
2122 num_bits =
2123 b_all_bits_are_locks
2124 ? TAG_BITS_PER_BYTE
2125 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dynamic_locks].tlv_index]
2126 .num_bits %
2127 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002128
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002129 if ((bytes_locked_per_bit * (num_bits - bit_count)) + byte_count <
2130 upper_offset) {
2131 /* Collect all lock bits that covers the current segment */
2132 byte_count += bytes_locked_per_bit * (num_bits - bit_count);
2133 total_bits += num_bits - bit_count;
2134 bit_count = 0;
2135 *p_end_byte = num_dynamic_locks;
2136 num_dynamic_locks++;
2137 } else {
2138 /* The last lock byte that covers the current segment */
2139 bit_count = 0;
2140 while (bit_count < num_bits) {
2141 /* The last lock bit that is used to lock this segment */
2142 byte_count += bytes_locked_per_bit;
2143 if (byte_count >= upper_offset) {
2144 *p_end_byte = num_dynamic_locks;
2145 total_bits += (bit_count + 1);
2146 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002147 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002148 bit_count++;
2149 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002150 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002151 }
2152 return total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002153}
2154
2155/*******************************************************************************
2156**
2157** Function rw_t2t_update_lock_attributes
2158**
2159** Description This function will check if the tag index passed as
2160** argument is a locked byte and return TRUE or FALSE
2161**
2162** Parameters: index, the index of the byte in the tag
2163**
2164**
2165** Returns TRUE, if the specified index in the tag is a locked or
2166** reserved or otp byte
2167** FALSE, otherwise
2168**
2169*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002170static void rw_t2t_update_lock_attributes(void) {
2171 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2172 uint8_t xx = 0;
2173 uint8_t num_static_lock_bytes = 0;
2174 uint8_t num_dyn_lock_bytes = 0;
2175 uint8_t bits_covered = 0;
2176 uint8_t bytes_covered = 0;
2177 uint8_t block_count = 0;
2178 bool b_all_bits_are_locks = true;
2179 uint8_t bytes_locked_per_lock_bit;
2180 uint8_t start_lock_byte;
2181 uint8_t start_lock_bit;
2182 uint8_t end_lock_byte;
2183 uint8_t num_lock_bits;
2184 uint8_t total_bits;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002185
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002186 /* Prepare lock_attr for the current segment */
2187 memset(p_t2t->lock_attr, 0, RW_T2T_SEGMENT_SIZE * sizeof(uint8_t));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002188
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002189 block_count = 0;
2190 if (p_t2t->segment == 0) {
2191 /* Update lock_attributes based on static lock bytes */
2192 xx = 0;
2193 num_static_lock_bytes = 0;
2194 block_count = 0;
2195 num_lock_bits =
2196 TAG_BITS_PER_BYTE - 1; /* the inner while loop increases xx by 2. need
2197 (-1) to avoid coverity overrun error */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002198
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002199 while (num_static_lock_bytes < T2T_NUM_STATIC_LOCK_BYTES) {
2200 /* Update lock attribute based on 2 static locks */
2201 while (xx < num_lock_bits) {
2202 p_t2t->lock_attr[block_count] = 0x00;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002203
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002204 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2205 rw_t2t_mask_bits[xx++]) {
2206 /* If the bit is set then 1 block is locked */
2207 p_t2t->lock_attr[block_count] = 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002208 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002209
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002210 if (p_t2t->tag_hdr[T2T_STATIC_LOCK0 + num_static_lock_bytes] &
2211 rw_t2t_mask_bits[xx++]) {
2212 /* If the bit is set then 1 block is locked */
2213 p_t2t->lock_attr[block_count] |= 0xF0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002214 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002215 block_count++;
2216 }
2217 num_static_lock_bytes++;
2218 xx = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002219 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002220 /* UID is always locked, irrespective of the lock value */
2221 p_t2t->lock_attr[0x00] = 0xFF;
2222 }
2223
2224 /* Get lock bits applicable for the current segment */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002225 total_bits = rw_t2t_get_lock_bits_for_segment(
2226 p_t2t->segment, &start_lock_byte, &start_lock_bit, &end_lock_byte);
2227 if (total_bits != 0) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002228 /* update lock_attributes based on current segment using dynamic lock bytes
2229 */
2230 xx = start_lock_bit;
2231 num_dyn_lock_bytes = start_lock_byte;
2232 bits_covered = 0;
2233 bytes_covered = 0;
2234 num_lock_bits = TAG_BITS_PER_BYTE;
2235 p_t2t->lock_attr[block_count] = 0;
2236
2237 while (num_dyn_lock_bytes <= end_lock_byte) {
2238 bytes_locked_per_lock_bit =
2239 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2240 .bytes_locked_per_bit;
2241 /* Find number of bits in the byte are lock bits */
2242 b_all_bits_are_locks =
2243 ((p_t2t->lockbyte[num_dyn_lock_bytes].byte_index + 1) *
2244 TAG_BITS_PER_BYTE <=
2245 p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2246 .num_bits);
2247 num_lock_bits =
2248 b_all_bits_are_locks
2249 ? TAG_BITS_PER_BYTE
2250 : p_t2t->lock_tlv[p_t2t->lockbyte[num_dyn_lock_bytes].tlv_index]
2251 .num_bits %
2252 TAG_BITS_PER_BYTE;
2253
2254 while (xx < num_lock_bits) {
2255 bytes_covered = 0;
2256 while (bytes_covered < bytes_locked_per_lock_bit) {
2257 if (p_t2t->lockbyte[num_dyn_lock_bytes].lock_byte &
2258 rw_t2t_mask_bits[xx]) {
2259 /* If the bit is set then it is locked */
2260 p_t2t->lock_attr[block_count] |= 0x01 << bits_covered;
2261 }
2262 bytes_covered++;
2263 bits_covered++;
2264 if (bits_covered == TAG_BITS_PER_BYTE) {
2265 /* Move to next 8 bytes */
2266 bits_covered = 0;
2267 block_count++;
2268 /* Assume unlocked before updating using locks */
2269 if (block_count < RW_T2T_SEGMENT_SIZE)
2270 p_t2t->lock_attr[block_count] = 0;
2271 }
2272 }
2273 xx++;
2274 }
2275 num_dyn_lock_bytes++;
2276 xx = 0;
2277 }
2278 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002279}
2280
2281/*******************************************************************************
2282**
2283** Function rw_t2t_is_lock_res_byte
2284**
2285** Description This function will check if the tag index passed as
2286** argument is a lock or reserved or otp byte and return
2287** TRUE or FALSE
2288**
2289** Parameters: index, the index of the byte in the tag
2290**
2291**
2292** Returns TRUE, if the specified index in the tag is a locked or
2293** reserved or otp byte
2294** FALSE, otherwise
2295**
2296*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002297static bool rw_t2t_is_lock_res_byte(uint16_t index) {
2298 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002299
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002300 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002301
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002302 if (p_t2t->attr_seg != p_t2t->segment) {
2303 /* Update attributes for the current segment */
2304 rw_t2t_update_attributes();
2305 p_t2t->attr_seg = p_t2t->segment;
2306 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002307
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002308 index = index % RW_T2T_SEGMENT_BYTES;
2309 /* Every bit in p_t2t->attr indicates one specific byte of the tag is either a
2310 * lock/reserved byte or not
2311 * So, each array element in p_t2t->attr covers two blocks in the tag as T2
2312 * block size is 4 and array element size is 8
2313 * Find the block and offset for the index (passed as argument) and Check if
2314 * the offset bit in the
2315 * p_t2t->attr[block/2] is set or not. If the bit is set then it is a
2316 * lock/reserved byte, otherwise not */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002317
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002318 return ((p_t2t->attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0) ? false
2319 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002320}
2321
2322/*******************************************************************************
2323**
2324** Function rw_t2t_is_read_only_byte
2325**
2326** Description This function will check if the tag index passed as
2327** argument is a locked and return
2328** TRUE or FALSE
2329**
2330** Parameters: index, the index of the byte in the tag
2331**
2332**
2333** Returns TRUE, if the specified index in the tag is a locked or
2334** reserved or otp byte
2335** FALSE, otherwise
2336**
2337*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002338static bool rw_t2t_is_read_only_byte(uint16_t index) {
2339 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002340
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002341 p_t2t->segment = (uint8_t)(index / RW_T2T_SEGMENT_BYTES);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002342
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002343 if (p_t2t->lock_attr_seg != p_t2t->segment) {
2344 /* Update lock attributes for the current segment */
2345 rw_t2t_update_lock_attributes();
2346 p_t2t->lock_attr_seg = p_t2t->segment;
2347 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002348
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002349 index = index % RW_T2T_SEGMENT_BYTES;
2350 /* Every bit in p_t2t->lock_attr indicates one specific byte of the tag is a
2351 * read only byte or read write byte
2352 * So, each array element in p_t2t->lock_attr covers two blocks of the tag as
2353 * T2 block size is 4 and array element size is 8
2354 * Find the block and offset for the index (passed as argument) and Check if
2355 * the offset bit in
2356 * p_t2t->lock_attr[block/2] is set or not. If the bit is set then it is a
2357 * read only byte, otherwise read write byte */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002358
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002359 return ((p_t2t->lock_attr[index / 8] & rw_t2t_mask_bits[index % 8]) == 0)
2360 ? false
2361 : true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002362}
2363
2364/*******************************************************************************
2365**
2366** Function rw_t2t_set_dynamic_lock_bits
2367**
2368** Description This function will set dynamic lock bits as part of
2369** configuring tag as read only
2370**
2371** Returns
2372** NFC_STATUS_OK, Command sent to set dynamic lock bits
2373** NFC_STATUS_FAILED: otherwise
2374**
2375*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002376tNFC_STATUS rw_t2t_set_dynamic_lock_bits(uint8_t* p_data) {
2377 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2378 uint8_t write_block[T2T_BLOCK_SIZE];
2379 uint16_t offset;
2380 uint16_t next_offset;
2381 uint8_t num_bits;
2382 uint8_t next_num_bits;
2383 tNFC_STATUS status = NFC_STATUS_FAILED;
2384 uint8_t num_locks;
2385 uint8_t lock_count;
2386 bool b_all_bits_are_locks = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002387
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002388 num_locks = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002389
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002390 memcpy(write_block, p_data, T2T_BLOCK_SIZE);
2391 while (num_locks < p_t2t->num_lockbytes) {
2392 if (p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
2393 offset = p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].offset +
2394 p_t2t->lockbyte[num_locks].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002395
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002396 /* Check if all bits are lock bits in the byte */
2397 b_all_bits_are_locks =
2398 ((p_t2t->lockbyte[num_locks].byte_index + 1) * TAG_BITS_PER_BYTE <=
2399 p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits);
2400 num_bits =
2401 b_all_bits_are_locks
2402 ? TAG_BITS_PER_BYTE
2403 : p_t2t->lock_tlv[p_t2t->lockbyte[num_locks].tlv_index].num_bits %
2404 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002405
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002406 write_block[(uint8_t)(offset % T2T_BLOCK_SIZE)] |=
2407 tags_pow(2, num_bits) - 1;
2408 lock_count = num_locks + 1;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002409
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002410 /* Set all the lock bits in the block using a sing block write command */
2411 while (lock_count < p_t2t->num_lockbytes) {
2412 next_offset =
2413 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].offset +
2414 p_t2t->lockbyte[lock_count].byte_index;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002415
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002416 /* Check if all bits are lock bits in the byte */
2417 b_all_bits_are_locks =
2418 ((p_t2t->lockbyte[lock_count].byte_index + 1) * TAG_BITS_PER_BYTE <=
2419 p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index].num_bits);
2420 next_num_bits =
2421 b_all_bits_are_locks
2422 ? TAG_BITS_PER_BYTE
2423 : p_t2t->lock_tlv[p_t2t->lockbyte[lock_count].tlv_index]
2424 .num_bits %
2425 TAG_BITS_PER_BYTE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002426
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002427 if (next_offset / T2T_BLOCK_SIZE == offset / T2T_BLOCK_SIZE) {
2428 write_block[(uint8_t)(next_offset % T2T_BLOCK_SIZE)] |=
2429 tags_pow(2, next_num_bits) - 1;
2430 } else
2431 break;
2432 lock_count++;
2433 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002434
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002435 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
2436 /* send WRITE command to set dynamic lock bits */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002437 status = rw_t2t_write((uint16_t)(offset / T2T_BLOCK_SIZE), write_block);
2438 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002439 while (lock_count > num_locks) {
2440 /* Set update initiated flag to indicate a write command is sent to
2441 * set dynamic lock bits of the block */
2442 p_t2t->lockbyte[lock_count - 1].lock_status =
2443 RW_T2T_LOCK_UPDATE_INITIATED;
2444 lock_count--;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002445 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002446 } else
2447 status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002448
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002449 break;
2450 }
2451 num_locks++;
2452 }
2453
2454 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002455}
2456
2457/*******************************************************************************
2458**
2459** Function rw_t2t_set_lock_tlv
2460**
2461** Description This function will set lock control tlv on the blank
2462** activated type 2 tag based on values read from version block
2463**
2464** Parameters: TAG data memory size
2465**
2466** Returns
2467** NFC_STATUS_OK, Command sent to set Lock TLV
2468** NFC_STATUS_FAILED: otherwise
2469**
2470*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002471tNFC_STATUS rw_t2t_set_lock_tlv(uint16_t addr, uint8_t num_dyn_lock_bits,
2472 uint16_t locked_area_size) {
2473 tNFC_STATUS status = NFC_STATUS_FAILED;
2474 int8_t PageAddr = 0;
2475 int8_t BytePerPage = 0;
2476 int8_t ByteOffset = 0;
2477 uint8_t a;
2478 uint8_t data_block[T2T_BLOCK_SIZE];
2479 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2480 uint8_t* p;
2481 uint8_t xx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002482
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002483 for (xx = 15; xx > 0; xx--) {
2484 a = (uint8_t)(addr / xx);
2485 a += (addr % xx) ? 1 : 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002486
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002487 BytePerPage = (int8_t)tags_log2(a);
2488 ByteOffset = (int8_t)(addr - xx * tags_pow(2, BytePerPage));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002489
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002490 if (ByteOffset < 16) {
2491 PageAddr = xx;
2492 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002493 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002494 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002495
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002496 if ((ByteOffset < 16) && (BytePerPage < 16) && (PageAddr < 16)) {
2497 memset(data_block, 0, T2T_BLOCK_SIZE);
2498 p = data_block;
2499 UINT8_TO_BE_STREAM(p, T2T_TLV_TYPE_LOCK_CTRL);
2500 UINT8_TO_BE_STREAM(p, T2T_TLEN_LOCK_CTRL_TLV);
2501 UINT8_TO_BE_STREAM(p, (PageAddr << 4 | ByteOffset));
2502 UINT8_TO_BE_STREAM(p, num_dyn_lock_bits);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002503
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002504 p_t2t->tlv_value[0] = PageAddr << 4 | ByteOffset;
2505 p_t2t->tlv_value[1] = num_dyn_lock_bits;
2506 p_t2t->tlv_value[2] =
2507 (uint8_t)(BytePerPage << 4 | tags_log2(locked_area_size));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002508
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002509 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_LOCK_TLV;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002510
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002511 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002512 status = rw_t2t_write(T2T_FIRST_DATA_BLOCK, data_block);
2513 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002514 p_t2t->b_read_data = false;
2515 } else
2516 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2517 } else
2518 status = NFC_STATUS_REJECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002519
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002520 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002521}
2522
2523/*******************************************************************************
2524**
2525** Function rw_t2t_set_cc
2526**
2527** Description This function will set Capability Container on the activated
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002528** type 2 tag with default values of CC0, CC1, CC4 and
2529** specified CC3 value
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002530**
2531** Parameters: CC3 value of the tag
2532**
2533** Returns
2534** NFC_STATUS_OK, Command sent to set CC
2535** NFC_STATUS_FAILED: otherwise
2536**
2537*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002538tNFC_STATUS rw_t2t_set_cc(uint8_t tms) {
2539 uint8_t cc_block[T2T_BLOCK_SIZE];
2540 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2541 tNFC_STATUS status = NFC_STATUS_FAILED;
2542 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002543
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002544 memset(cc_block, 0, T2T_BLOCK_SIZE);
2545 memset(p_t2t->ndef_final_block, 0, T2T_BLOCK_SIZE);
2546 p = cc_block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002547
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002548 /* Prepare Capability Container */
2549 UINT8_TO_BE_STREAM(p, T2T_CC0_NMN);
2550 UINT8_TO_BE_STREAM(p, T2T_CC1_VNO);
2551 UINT8_TO_BE_STREAM(p, tms);
2552 UINT8_TO_BE_STREAM(p, T2T_CC3_RWA_RW);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002553
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002554 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002555
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002556 /* send WRITE-E8 command */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002557 status = rw_t2t_write(T2T_CC_BLOCK, cc_block);
2558 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002559 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2560 p_t2t->b_read_hdr = false;
2561 } else
2562 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002563
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002564 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002565}
2566
2567/*******************************************************************************
2568**
2569** Function rw_t2t_format_tag
2570**
2571** Description This function will format tag based on Manufacturer ID
2572**
2573** Returns
2574** NFC_STATUS_OK, Command sent to format Tag
2575** NFC_STATUS_FAILED: otherwise
2576**
2577*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002578tNFC_STATUS rw_t2t_format_tag(void) {
2579 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2580 const tT2T_INIT_TAG* p_ret;
2581 uint8_t tms;
2582 tNFC_STATUS status = NFC_STATUS_FAILED;
2583 bool b_blank_tag = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002584
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002585 p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
2586 if (p_ret == NULL) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002587 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002588 "rw_t2t_format_tag - Unknown Manufacturer ID: %u, Cannot Format the "
2589 "tag!",
2590 p_t2t->tag_hdr[0]);
2591 return (NFC_STATUS_FAILED);
2592 }
2593
2594 if (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != 0) {
2595 /* If OTP tag has valid NDEF Message, cannot format the tag */
2596 if ((p_t2t->ndef_msg_len > 0) && (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002597 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002598 "rw_t2t_format_tag - Cannot Format a OTP tag with NDEF Message!");
2599 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002600 }
2601
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002602 if (((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0) &&
2603 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) ||
2604 ((p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != 0) &&
2605 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_LEGACY_VNO) &&
2606 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_VNO) &&
2607 (p_t2t->tag_hdr[T2T_CC1_VNO_BYTE] != T2T_CC1_NEW_VNO))) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002608 LOG(WARNING) << StringPrintf(
2609 "rw_t2t_format_tag - Tag not blank to Format!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002610 return (NFC_STATUS_FAILED);
2611 } else {
2612 tms = p_t2t->tag_hdr[T2T_CC2_TMS_BYTE];
2613 b_blank_tag = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002614 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002615 } else
2616 tms = p_ret->tms;
2617
2618 memset(p_t2t->tag_data, 0, T2T_READ_DATA_LEN);
2619
2620 if (!b_blank_tag || !p_ret->b_multi_version) {
2621 status = rw_t2t_set_cc(tms);
2622 } else if (p_ret->version_block != 0) {
2623 /* If Version number is not read, READ it now */
2624 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2625
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002626 status = rw_t2t_read(p_ret->version_block);
2627 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002628 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002629 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002630 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2631 } else {
2632 /* UID block is the version block */
2633 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
2634 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_VERSION_INFO;
2635 rw_t2t_handle_format_tag_rsp(p_t2t->tag_hdr);
2636 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002637
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002638 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002639}
2640
2641/*******************************************************************************
2642**
2643** Function rw_t2t_soft_lock_tag
2644**
2645** Description This function will soft lock the tag after validating CC.
2646**
2647** Returns
2648** NFC_STATUS_OK, Command sent to soft lock the tag
2649** NFC_STATUS_FAILED: otherwise
2650**
2651*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002652tNFC_STATUS rw_t2t_soft_lock_tag(void) {
2653 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2654 tNFC_STATUS status = NFC_STATUS_FAILED;
2655 uint8_t write_block[T2T_BLOCK_SIZE];
2656 uint8_t num_locks;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002657
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002658 /* If CC block is read and cc3 is soft locked, reject the command */
2659 if ((p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] & T2T_CC3_RWA_RO) == T2T_CC3_RWA_RO) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002660 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002661 "rw_t2t_soft_lock_tag: Error: Type 2 tag is in Read only state, CC3: "
2662 "%u",
2663 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2664 return (NFC_STATUS_FAILED);
2665 }
2666
2667 if (p_t2t->b_hard_lock) {
2668 /* Should have performed NDEF Detection on dynamic memory structure tag,
2669 * before permanently converting to Read only
2670 * Even when no lock control tlv is present, default lock bytes should be
2671 * present */
2672
2673 if ((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] != T2T_CC2_TMS_STATIC) &&
2674 (p_t2t->num_lockbytes == 0)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002675 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002676 "rw_t2t_soft_lock_tag: Error: Lock TLV not detected! Cannot hard "
2677 "lock the tag");
2678 return (NFC_STATUS_FAILED);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002679 }
2680
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002681 /* On dynamic memory structure tag, reset all lock bytes status to 'Not
2682 * Updated' if not in Updated status */
2683 num_locks = 0;
2684 while (num_locks < p_t2t->num_lockbytes) {
2685 if (p_t2t->lockbyte[num_locks].lock_status != RW_T2T_LOCK_UPDATED)
2686 p_t2t->lockbyte[num_locks].lock_status = RW_T2T_LOCK_NOT_UPDATED;
2687 num_locks++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002688 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002689 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002690
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002691 memcpy(write_block, &p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], T2T_BLOCK_SIZE);
2692 write_block[(T2T_CC3_RWA_BYTE % T2T_BLOCK_SIZE)] = T2T_CC3_RWA_RO;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002693
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002694 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_CC_RO;
2695 /* First Soft lock the tag */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002696 status = rw_t2t_write(T2T_CC_BLOCK, write_block);
2697 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002698 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
2699 p_t2t->b_read_hdr = false;
2700 } else {
2701 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2702 }
2703 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002704}
2705
2706/*****************************************************************************
2707**
2708** Function RW_T2tFormatNDef
2709**
2710** Description
2711** Format Tag content
2712**
2713** Returns
2714** NFC_STATUS_OK, Command sent to format Tag
2715** NFC_STATUS_FAILED: otherwise
2716**
2717*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002718tNFC_STATUS RW_T2tFormatNDef(void) {
2719 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2720 tNFC_STATUS status = NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002721
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002722 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002723 LOG(WARNING) << StringPrintf(
2724 "RW_T2tFormatNDef - Tag not initialized/ Busy! State: %u",
2725 p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002726 return (NFC_STATUS_FAILED);
2727 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002728
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002729 if (!p_t2t->b_read_hdr) {
2730 /* If UID is not read, READ it now */
2731 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002732
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002733 status = rw_t2t_read(0);
2734 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002735 p_t2t->state = RW_T2T_STATE_FORMAT_TAG;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002736 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002737 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2738 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002739 status = rw_t2t_format_tag();
2740 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002741 }
2742 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002743}
2744
2745/*******************************************************************************
2746**
2747** Function RW_T2tLocateTlv
2748**
2749** Description This function is used to perform TLV detection on a Type 2
2750** tag, and retrieve the tag's TLV attribute information.
2751**
2752** Before using this API, the application must call
2753** RW_SelectTagType to indicate that a Type 2 tag has been
2754** activated.
2755**
2756** Parameters: tlv_type : TLV to detect
2757**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002758** Returns NCI_STATUS_OK, if detection was started. Otherwise, error
2759** status.
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002760**
2761*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002762tNFC_STATUS RW_T2tLocateTlv(uint8_t tlv_type) {
2763 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2764 tNFC_STATUS status;
2765 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002766
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002767 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002768 LOG(ERROR) << StringPrintf(
2769 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002770 return (NFC_STATUS_BUSY);
2771 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002772
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002773 if ((tlv_type != TAG_LOCK_CTRL_TLV) && (tlv_type != TAG_MEM_CTRL_TLV) &&
2774 (tlv_type != TAG_NDEF_TLV) && (tlv_type != TAG_PROPRIETARY_TLV)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002775 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2776 "RW_T2tLocateTlv - Cannot search TLV: 0x%02x", tlv_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002777 return (NFC_STATUS_FAILED);
2778 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002779
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002780 if ((tlv_type == TAG_LOCK_CTRL_TLV) && (p_t2t->b_read_hdr) &&
2781 (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] == T2T_CC2_TMS_STATIC)) {
2782 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002783 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002784 "RW_T2tLocateTlv - No Lock tlv in static structure tag, CC[0]: 0x%02x",
2785 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE]);
2786 return (NFC_STATUS_FAILED);
2787 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002788
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002789 if ((tlv_type == TAG_NDEF_TLV) && (p_t2t->b_read_hdr) &&
2790 (p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN)) {
2791 p_t2t->b_read_hdr = false;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002792 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002793 "RW_T2tLocateTlv - Invalid NDEF Magic Number!, CC[0]: 0x%02x, CC[1]: "
2794 "0x%02x, CC[3]: 0x%02x",
2795 p_t2t->tag_hdr[T2T_CC0_NMN_BYTE], p_t2t->tag_hdr[T2T_CC1_VNO_BYTE],
2796 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
2797 return (NFC_STATUS_FAILED);
2798 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002799
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002800 p_t2t->work_offset = 0;
2801 p_t2t->tlv_detect = tlv_type;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002802
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002803 /* Reset control block variables based on type of tlv to detect */
2804 if (tlv_type == TAG_LOCK_CTRL_TLV) {
2805 p_t2t->num_lockbytes = 0;
2806 p_t2t->num_lock_tlvs = 0;
2807 } else if (tlv_type == TAG_MEM_CTRL_TLV) {
2808 p_t2t->num_mem_tlvs = 0;
2809 } else if (tlv_type == TAG_NDEF_TLV) {
2810 p_t2t->ndef_msg_offset = 0;
2811 p_t2t->num_lockbytes = 0;
2812 p_t2t->num_lock_tlvs = 0;
2813 p_t2t->num_mem_tlvs = 0;
2814 p_t2t->ndef_msg_len = 0;
2815 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
2816 } else {
2817 p_t2t->prop_msg_len = 0;
2818 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002819
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002820 if (!p_t2t->b_read_hdr) {
2821 /* First read CC block */
2822 block = 0;
2823 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
2824 } else {
2825 /* Read first data block */
2826 block = T2T_FIRST_DATA_BLOCK;
2827 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
2828 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002829
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002830 /* Start reading tag, looking for the specified TLV */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002831 status = rw_t2t_read((uint16_t)block);
2832 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002833 p_t2t->state = RW_T2T_STATE_DETECT_TLV;
2834 } else {
2835 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2836 }
2837 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002838}
2839
2840/*******************************************************************************
2841**
2842** Function RW_T2tDetectNDef
2843**
2844** Description This function is used to perform NDEF detection on a Type 2
2845** tag, and retrieve the tag's NDEF attribute information.
2846**
2847** Before using this API, the application must call
2848** RW_SelectTagType to indicate that a Type 2 tag has been
2849** activated.
2850**
2851** Parameters: none
2852**
2853** Returns NCI_STATUS_OK,if detect op started.Otherwise,error status.
2854**
2855*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002856tNFC_STATUS RW_T2tDetectNDef(bool skip_dyn_locks) {
2857 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
Evan Chuc95c79c2013-04-12 17:38:09 -04002858
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002859 p_t2t->skip_dyn_locks = skip_dyn_locks;
Evan Chuc95c79c2013-04-12 17:38:09 -04002860
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002861 return RW_T2tLocateTlv(TAG_NDEF_TLV);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002862}
2863
2864/*******************************************************************************
2865**
2866** Function RW_T2tReadNDef
2867**
2868** Description Retrieve NDEF contents from a Type2 tag.
2869**
2870** The RW_T2T_NDEF_READ_EVT event is used to notify the
2871** application after reading the NDEF message.
2872**
2873** Before using this API, the RW_T2tDetectNDef function must
2874** be called to verify that the tag contains NDEF data, and to
2875** retrieve the NDEF attributes.
2876**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002877** Internally, this command will be separated into multiple
2878** Tag2 Read commands (if necessary) - depending on the NDEF
2879** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002880**
2881** Parameters: p_buffer: The buffer into which to read the NDEF message
2882** buf_len: The length of the buffer
2883**
2884** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
2885**
2886*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002887tNFC_STATUS RW_T2tReadNDef(uint8_t* p_buffer, uint16_t buf_len) {
2888 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2889 tNFC_STATUS status = NFC_STATUS_OK;
2890 uint16_t block;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002891
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002892 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002893 LOG(ERROR) << StringPrintf(
2894 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002895 return (NFC_STATUS_FAILED);
2896 }
2897
2898 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002899 LOG(ERROR) << StringPrintf(
2900 "RW_T2tReadNDef - Error: NDEF detection not performed yet");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002901 return (NFC_STATUS_FAILED);
2902 }
2903
2904 if (buf_len < p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002905 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002906 "RW_T2tReadNDef - buffer size: %u less than NDEF msg sise: %u",
2907 buf_len, p_t2t->ndef_msg_len);
2908 return (NFC_STATUS_FAILED);
2909 }
2910
2911 if (!p_t2t->ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002912 LOG(WARNING) << StringPrintf(
2913 "RW_T2tReadNDef - NDEF Message length is zero");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002914 return (NFC_STATUS_NOT_INITIALIZED);
2915 }
2916
2917 p_t2t->p_ndef_buffer = p_buffer;
2918 p_t2t->work_offset = 0;
2919
2920 block = (uint16_t)(p_t2t->ndef_msg_offset / T2T_BLOCK_LEN);
2921 block -= block % T2T_READ_BLOCKS;
2922
2923 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
2924
2925 if ((block == T2T_FIRST_DATA_BLOCK) && (p_t2t->b_read_data)) {
2926 p_t2t->state = RW_T2T_STATE_READ_NDEF;
2927 p_t2t->block_read = T2T_FIRST_DATA_BLOCK;
2928 rw_t2t_handle_ndef_read_rsp(p_t2t->tag_data);
2929 } else {
2930 /* Start reading NDEF Message */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002931 status = rw_t2t_read(block);
2932 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002933 p_t2t->state = RW_T2T_STATE_READ_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002934 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002935 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002936
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002937 return (status);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002938}
2939
2940/*******************************************************************************
2941**
2942** Function RW_T2tWriteNDef
2943**
2944** Description Write NDEF contents to a Type2 tag.
2945**
2946** Before using this API, the RW_T2tDetectNDef
2947** function must be called to verify that the tag contains
2948** NDEF data, and to retrieve the NDEF attributes.
2949**
2950** The RW_T2T_NDEF_WRITE_EVT callback event will be used to
2951** notify the application of the response.
2952**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002953** Internally, this command will be separated into multiple
2954** Tag2 Write commands (if necessary) - depending on the NDEF
2955** Msg size
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002956**
2957** Parameters: msg_len: The length of the buffer
2958** p_msg: The NDEF message to write
2959**
2960** Returns NCI_STATUS_OK,if write was started. Otherwise, error status
2961**
2962*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002963tNFC_STATUS RW_T2tWriteNDef(uint16_t msg_len, uint8_t* p_msg) {
2964 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
2965 uint16_t block;
2966 const tT2T_INIT_TAG* p_ret;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002967
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002968 tNFC_STATUS status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002969
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002970 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002971 LOG(ERROR) << StringPrintf(
2972 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002973 return (NFC_STATUS_FAILED);
2974 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002975
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002976 if (p_t2t->ndef_status == T2T_NDEF_NOT_DETECTED) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002977 LOG(ERROR) << StringPrintf(
2978 "RW_T2tWriteNDef - Error: NDEF detection not performed!");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002979 return (NFC_STATUS_FAILED);
2980 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002981
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002982 if (p_t2t->tag_hdr[T2T_CC3_RWA_BYTE] != T2T_CC3_RWA_RW) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002983 LOG(ERROR) << StringPrintf(
2984 "RW_T2tWriteNDef - Write access not granted - CC3: %u",
2985 p_t2t->tag_hdr[T2T_CC3_RWA_BYTE]);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002986 return (NFC_STATUS_REFUSED);
2987 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002988
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002989 /* Check if there is enough memory on the tag */
2990 if (msg_len > p_t2t->max_ndef_msg_len) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002991 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002992 "RW_T2tWriteNDef - Cannot write NDEF of size greater than %u bytes",
2993 p_t2t->max_ndef_msg_len);
2994 return (NFC_STATUS_FAILED);
2995 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002996
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002997 /* If OTP tag and tag has valid NDEF Message, stop writting new NDEF Message
2998 * as it may corrupt the tag */
2999 if ((p_t2t->ndef_msg_len > 0) &&
3000 ((p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0)) != NULL) &&
3001 (p_ret->b_otp)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003002 LOG(WARNING) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003003 "RW_T2tWriteNDef - Cannot Overwrite NDEF Message on a OTP tag!");
3004 return (NFC_STATUS_FAILED);
3005 }
3006 p_t2t->p_new_ndef_buffer = p_msg;
3007 p_t2t->new_ndef_msg_len = msg_len;
3008 p_t2t->work_offset = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003009
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003010 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK;
3011 /* Read first NDEF Block before updating NDEF */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003012
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003013 block = (uint16_t)(p_t2t->ndef_header_offset / T2T_BLOCK_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003014
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003015 if ((block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) &&
3016 (p_t2t->b_read_data)) {
3017 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
3018 p_t2t->block_read = block;
3019 rw_t2t_handle_ndef_write_rsp(
3020 &p_t2t->tag_data[(block - T2T_FIRST_DATA_BLOCK) * T2T_BLOCK_LEN]);
3021 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003022 status = rw_t2t_read(block);
3023 if (status == NFC_STATUS_OK)
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003024 p_t2t->state = RW_T2T_STATE_WRITE_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003025 else
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003026 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3027 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003028
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003029 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003030}
3031
3032/*******************************************************************************
3033**
3034** Function RW_T2tSetTagReadOnly
3035**
3036** Description This function can be called to set T2 tag as read only.
3037**
3038** Parameters: b_hard_lock: To indicate hard lock the tag or not
3039**
3040** Returns NCI_STATUS_OK, if setting tag as read only was started.
3041** Otherwise, error status.
3042**
3043*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003044tNFC_STATUS RW_T2tSetTagReadOnly(bool b_hard_lock) {
3045 tNFC_STATUS status = NFC_STATUS_FAILED;
3046 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003047
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003048 if (p_t2t->state != RW_T2T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07003049 LOG(ERROR) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003050 "RW_T2tSetTagReadOnly: Error: Type 2 tag not activated or Busy - "
3051 "State: %u",
3052 p_t2t->state);
3053 return (NFC_STATUS_FAILED);
3054 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003055
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003056 p_t2t->b_hard_lock = b_hard_lock;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003057
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003058 if (!p_t2t->b_read_hdr) {
3059 /* Read CC block before configuring tag as Read only */
3060 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_CC;
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003061 status = rw_t2t_read((uint16_t)0);
3062 if (status == NFC_STATUS_OK) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003063 p_t2t->state = RW_T2T_STATE_SET_TAG_RO;
3064 } else
3065 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
3066 } else {
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08003067 status = rw_t2t_soft_lock_tag();
3068 if (status != NFC_STATUS_OK) p_t2t->b_read_hdr = false;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003069 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003070
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08003071 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08003072}
3073
Ruchi Kandoi303fec12016-12-14 13:22:38 -08003074#endif /* (RW_NDEF_INCLUDED == TRUE) */