1 /******************************************************************************
2 *
3 * Copyright (C) 2020 STMicroelectronics
4 *
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 specific NFC Forum T5T operations
22 * in Reader/Writer mode.
23 *
24 ******************************************************************************/
25
26 #include <android-base/logging.h>
27 #include <android-base/stringprintf.h>
28 #include <log/log.h>
29 #include <string.h>
30
31 #include "bt_types.h"
32 #include "nfc_api.h"
33 #include "nfc_int.h"
34 #include "nfc_target.h"
35 #include "rw_api.h"
36 #include "rw_int.h"
37
38 using android::base::StringPrintf;
39
40 extern void rw_i93_handle_error(tNFC_STATUS);
41 extern tNFC_STATUS rw_i93_get_next_blocks(uint32_t);
42 extern tNFC_STATUS rw_i93_send_cmd_read_single_block(uint32_t, bool);
43 extern tNFC_STATUS rw_i93_send_cmd_write_single_block(uint32_t, uint8_t*);
44 extern tNFC_STATUS rw_i93_send_cmd_lock_block(uint32_t);
45 extern bool rw_i93_process_sys_info(uint8_t* p_data, uint16_t length);
46
47 /*******************************************************************************
48 **
49 ** Function rw_t5t_sm_detect_ndef
50 **
51 ** Description Process NDEF detection procedure
52 **
53 ** 1. Get UID if not having yet
54 ** 2. Get System Info if not having yet
55 ** 3. Read first block for CC
56 ** 4. Search NDEF Type and length
57 ** 5. Get block status to get max NDEF size and read-only
58 ** status
59 **
60 ** Returns void
61 **
62 *******************************************************************************/
rw_t5t_sm_detect_ndef(NFC_HDR * p_resp)63 void rw_t5t_sm_detect_ndef(NFC_HDR* p_resp) {
64 uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
65 uint8_t flags, cc[8];
66 uint32_t t5t_area_len = 0;
67 uint16_t length = p_resp->len, xx;
68 tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
69 tRW_DATA rw_data;
70 tNFC_STATUS status = NFC_STATUS_FAILED;
71
72 LOG(VERBOSE) << StringPrintf(
73 "%s - sub_state:%s (0x%x)", __func__,
74 rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
75
76 if (length == 0) {
77 android_errorWriteLog(0x534e4554, "121260197");
78 rw_i93_handle_error(NFC_STATUS_FAILED);
79 return;
80 }
81 STREAM_TO_UINT8(flags, p);
82 length--;
83
84 if (flags & I93_FLAG_ERROR_DETECTED) {
85 LOG(VERBOSE) << StringPrintf("%s - Got error flags (0x%02x)", __func__,
86 flags);
87 rw_i93_handle_error(NFC_STATUS_FAILED);
88 return;
89 }
90
91 switch (p_i93->sub_state) {
92 case RW_I93_SUBSTATE_WAIT_CC_EXT:
93
94 /* assume block size is 4 */
95 STREAM_TO_ARRAY(cc, p, 4);
96
97 status = NFC_STATUS_FAILED;
98
99 /*
100 ** Capability Container (CC) second block
101 **
102 ** CC[4] : RFU
103 ** CC[5] : RFU
104 ** CC[6] : MSB MLEN
105 ** CC[7] : LSB MLEN
106 */
107
108 LOG(VERBOSE) << StringPrintf("%s - cc[4-7]: 0x%02X 0x%02X 0x%02X 0x%02X",
109 __func__, cc[0], cc[1], cc[2], cc[3]);
110
111 /* T5T_Area length = 8 * MLEN */
112 /* CC is 8-byte, MLEN is defined by bytes 6 & 7 */
113 t5t_area_len = cc[3] + (cc[2] << 8);
114 t5t_area_len <<= 3;
115 p_i93->max_ndef_length = t5t_area_len;
116
117 p_i93->t5t_area_last_offset = t5t_area_len + 8 - 1;
118 memcpy((uint8_t*)&rw_cb.tcb.i93.gre_cc_content[4], (uint8_t*)cc, 4);
119 p_i93->num_block = t5t_area_len / p_i93->block_size;
120 p_i93->t5t_area_start_block = 2;
121
122 LOG(VERBOSE) << StringPrintf(
123 "%s - T5T Area size:%d, Nb blocks:0x%04X, Block size:0x%02X, "
124 "T5T Area last offset:%d",
125 __func__, t5t_area_len, p_i93->num_block, p_i93->block_size,
126 p_i93->t5t_area_last_offset);
127
128 status = NFC_STATUS_OK;
129
130 /* search NDEF TLV from offset 8 when CC file coded on 8 bytes NFC Forum
131 */
132 p_i93->rw_offset = 8;
133
134 if (p_i93->gre_cc_content[0] == I93_ICODE_CC_MAGIC_NUMER_E2) {
135 p_i93->intl_flags |= RW_I93_FLAG_EXT_COMMANDS;
136 }
137
138 if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
139 p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
140 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
141 } else {
142 rw_i93_handle_error(NFC_STATUS_FAILED);
143 }
144 break;
145
146 case RW_I93_SUBSTATE_WAIT_SYS_INFO:
147
148 p_i93->block_size = 0;
149 p_i93->num_block = 0;
150
151 if (!rw_i93_process_sys_info(p, length)) {
152 /* retrying with protocol extension flag */
153 break;
154 }
155
156 if ((p_i93->block_size == 0) || (p_i93->num_block == 0)) {
157 LOG(DEBUG) << StringPrintf("%s; Unable to get tag memory size",
158 __func__);
159 rw_i93_handle_error(status);
160 } else {
161 /* read CC in the first block */
162 if (rw_i93_send_cmd_read_single_block(0x0000, false) == NFC_STATUS_OK) {
163 p_i93->sub_state = RW_I93_SUBSTATE_WAIT_CC;
164 } else {
165 rw_i93_handle_error(NFC_STATUS_FAILED);
166 }
167 }
168 break;
169
170 case RW_I93_SUBSTATE_WAIT_CC:
171
172 if (length < RW_I93_CC_SIZE) {
173 android_errorWriteLog(0x534e4554, "139188579");
174 rw_i93_handle_error(NFC_STATUS_FAILED);
175 return;
176 }
177
178 /* assume block size is more than RW_I93_CC_SIZE 4 */
179 STREAM_TO_ARRAY(cc, p, RW_I93_CC_SIZE);
180
181 status = NFC_STATUS_FAILED;
182
183 /*
184 ** Capability Container (CC)
185 **
186 ** CC[0] : magic number (0xE1)
187 ** CC[1] : Bit 7-6:Major version number
188 ** : Bit 5-4:Minor version number
189 ** : Bit 3-2:Read access condition (00b: read access granted
190 ** without any security)
191 ** : Bit 1-0:Write access condition (00b: write access granted
192 ** without any security)
193 ** CC[2] : Memory size in 8 bytes (Ex. 0x04 is 32 bytes) [STM, set to
194 ** 0xFF if more than 2040bytes]
195 ** CC[3] : Bit 0:Read multiple blocks is supported [NXP, STM]
196 ** : Bit 1:Inventory page read is supported [NXP]
197 ** : Bit 2:More than 2040 bytes are supported [STM]
198 */
199
200 LOG(VERBOSE) << StringPrintf("%s - cc[0-3]: 0x%02X 0x%02X 0x%02X 0x%02X",
201 __func__, cc[0], cc[1], cc[2], cc[3]);
202
203 if ((cc[0] == I93_ICODE_CC_MAGIC_NUMER_E1) ||
204 (cc[0] == I93_ICODE_CC_MAGIC_NUMER_E2)) {
205 if ((cc[1] & 0xC0) > I93_VERSION_1_x) {
206 LOG(VERBOSE) << StringPrintf("%s - Major mapping version above 1 %d.x",
207 __func__, cc[1] >> 6);
208 /* major mapping version above 1 not supported */
209 rw_i93_handle_error(NFC_STATUS_FAILED);
210 break;
211 }
212
213 if ((cc[1] & I93_ICODE_CC_READ_ACCESS_MASK) ==
214 I93_ICODE_CC_READ_ACCESS_GRANTED) {
215 if ((cc[1] & I93_ICODE_CC_WRITE_ACCESS_MASK) !=
216 I93_ICODE_CC_WRITE_ACCESS_GRANTED) {
217 /* read-only or password required to write */
218 p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
219 }
220 if (cc[3] & I93_ICODE_CC_MBREAD_MASK) {
221 /* tag supports read multiple blocks command */
222 p_i93->intl_flags |= RW_I93_FLAG_READ_MULTI_BLOCK;
223 }
224
225 if (cc[3] & I93_ICODE_CC_SPECIAL_FRAME_MASK) {
226 /* tag supports Special Frame for Write-Alike commands */
227 p_i93->intl_flags |= RW_I93_FLAG_SPECIAL_FRAME;
228 }
229
230 /* get block size from length of the first READ_SINGLE_BLOCK response
231 */
232 if (length == I93_BLEN_4BYTES)
233 p_i93->block_size = I93_BLEN_4BYTES;
234 else if (length == I93_BLEN_8BYTES)
235 p_i93->block_size = I93_BLEN_8BYTES;
236 else if (length == I93_BLEN_16BYTES)
237 p_i93->block_size = I93_BLEN_16BYTES;
238 else if (length == I93_BLEN_32BYTES)
239 p_i93->block_size = I93_BLEN_32BYTES;
240 else {
241 rw_i93_handle_error(NFC_STATUS_FAILED);
242 break;
243 }
244
245 /* T5T_Area length = 8 * MLEN */
246 if (cc[2] == 0) {
247 /* CC is 8-byte, MLEN is defined by bytes 6 & 7 */
248 if (length >= I93_BLEN_8BYTES) {
249 STREAM_TO_ARRAY(&cc[4], p, 4);
250 LOG(VERBOSE) << StringPrintf(
251 "%s - cc[4-7]: 0x%02X 0x%02X 0x%02X 0x%02X", __func__, cc[4],
252 cc[5], cc[6], cc[7]);
253 t5t_area_len = cc[7] + (cc[6] << 8);
254 t5t_area_len <<= 3;
255
256 p_i93->t5t_area_last_offset = t5t_area_len + 8 - 1;
257 p_i93->max_ndef_length = t5t_area_len;
258 p_i93->t5t_area_start_block = 1;
259
260 memcpy(p_i93->gre_cc_content, cc, 8);
261 } else {
262 /* require an additional read to get the second half of the
263 * CC from block 1 */
264 if (rw_i93_send_cmd_read_single_block(0x0001, false) ==
265 NFC_STATUS_OK) {
266 p_i93->sub_state = RW_I93_SUBSTATE_WAIT_CC_EXT;
267 } else {
268 rw_i93_handle_error(NFC_STATUS_FAILED);
269 }
270 memcpy(p_i93->gre_cc_content, cc, 4);
271 break;
272 }
273 } else {
274 /* CC is 4-byte, MLEN is defined by byte 2 */
275 t5t_area_len = cc[2] << 3;
276 p_i93->t5t_area_last_offset = t5t_area_len + 4 - 1;
277 p_i93->t5t_area_start_block = 1;
278
279 memcpy(p_i93->gre_cc_content, cc, 4);
280 }
281
282 p_i93->num_block = t5t_area_len / p_i93->block_size;
283
284 p_i93->max_ndef_length = t5t_area_len;
285
286 if (cc[0] == I93_ICODE_CC_MAGIC_NUMER_E2) {
287 /* can only be done here if CC is coded over 4 bytes */
288 p_i93->intl_flags |= RW_I93_FLAG_EXT_COMMANDS;
289 }
290
291 LOG(VERBOSE) << StringPrintf(
292 "%s - T5T Area size:%d, Nb blocks:0x%04X, "
293 "Block size:0x%02X, T5T Area last offset:%d",
294 __func__, t5t_area_len, p_i93->num_block, p_i93->block_size,
295 p_i93->t5t_area_last_offset);
296
297 status = NFC_STATUS_OK;
298 }
299 }
300
301 if (status == NFC_STATUS_OK) {
302 /* search NDEF TLV from offset 4 when CC file coded on 4 bytes
303 * NFC Forum during the next block reading, if CC file is coded
304 * on more than 4 bytes, start searching for NDEF TLV in the current
305 * block read except if the CC
306 */
307 if (cc[2] == 0) {
308 /* 8-byte CC length */
309 p_i93->rw_offset = 8;
310
311 if (length > I93_BLEN_8BYTES) {
312 /* Rest of the block contains T5T_Area, look for NDEF TLV */
313 p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
314 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
315 /* start TLV search after CC in the first block */
316 } else {
317 /* 8-byte block length, NDEF TLV search must continue
318 * in the next block */
319 if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
320 p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
321 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
322 } else {
323 rw_i93_handle_error(NFC_STATUS_FAILED);
324 }
325 break;
326 }
327 } else {
328 /* 4-byte CC length */
329 p_i93->rw_offset = 4;
330
331 if (length > I93_BLEN_4BYTES) {
332 /* Rest of the block contains T5T_Area, look for NDEF TLV */
333 p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
334 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
335 /* start TLV search after CC in the first block */
336 } else {
337 if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
338 p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
339 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
340 } else {
341 rw_i93_handle_error(NFC_STATUS_FAILED);
342 }
343 break;
344 }
345 }
346 } else {
347 rw_i93_handle_error(NFC_STATUS_FAILED);
348 break;
349 }
350
351 FALLTHROUGH_INTENDED;
352
353 case RW_I93_SUBSTATE_SEARCH_NDEF_TLV:
354 /* search TLV within read blocks */
355 for (xx = 0; xx < length; xx++) {
356 /* if looking for type */
357 if (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_TYPE) {
358 if (*(p + xx) == I93_ICODE_TLV_TYPE_NDEF) {
359 /* store found type and get length field */
360 p_i93->tlv_type = *(p + xx);
361 p_i93->ndef_tlv_start_offset = p_i93->rw_offset + xx;
362
363 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_1;
364
365 } else if (*(p + xx) == I93_ICODE_TLV_TYPE_TERM) {
366 /* no NDEF TLV found */
367 p_i93->tlv_type = I93_ICODE_TLV_TYPE_TERM;
368 break;
369 } else {
370 /* TLV with Tag field set as RFU are not interpreted */
371 p_i93->tlv_type = *(p + xx);
372 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_1;
373 }
374 } else if (p_i93->tlv_detect_state ==
375 RW_I93_TLV_DETECT_STATE_LENGTH_1) {
376 /* if 3 bytes length field */
377 if (*(p + xx) == 0xFF) {
378 /* need 2 more bytes for length field */
379 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_2;
380 } else {
381 p_i93->tlv_length = *(p + xx);
382 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_VALUE;
383
384 if (p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
385 p_i93->ndef_tlv_last_offset =
386 p_i93->ndef_tlv_start_offset + 1 + p_i93->tlv_length;
387 break;
388 }
389 }
390 } else if (p_i93->tlv_detect_state ==
391 RW_I93_TLV_DETECT_STATE_LENGTH_2) {
392 /* the second byte of 3 bytes length field */
393 p_i93->tlv_length = *(p + xx);
394 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_3;
395
396 } else if (p_i93->tlv_detect_state ==
397 RW_I93_TLV_DETECT_STATE_LENGTH_3) {
398 /* the last byte of 3 bytes length field */
399 p_i93->tlv_length = (p_i93->tlv_length << 8) + *(p + xx);
400 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_VALUE;
401
402 if (p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
403 p_i93->ndef_tlv_last_offset =
404 p_i93->ndef_tlv_start_offset + 3 + p_i93->tlv_length;
405 break;
406 }
407 } else if (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_VALUE) {
408 /* this is other than NDEF TLV */
409 if (p_i93->tlv_length <= length - xx) {
410 /* skip value field */
411 xx += (uint8_t)p_i93->tlv_length - 1;
412 p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
413 } else {
414 /* read more data */
415 p_i93->tlv_length -= (length - xx);
416 break;
417 }
418 }
419 }
420
421 /* found NDEF TLV and read length field */
422 if ((p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) &&
423 (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_VALUE)) {
424 p_i93->ndef_length = p_i93->tlv_length;
425
426 rw_data.ndef.status = NFC_STATUS_OK;
427 rw_data.ndef.protocol = NFC_PROTOCOL_T5T;
428 rw_data.ndef.flags = 0;
429 rw_data.ndef.flags |= RW_NDEF_FL_SUPPORTED;
430 rw_data.ndef.flags |= RW_NDEF_FL_FORMATED; // NOTYPO
431 rw_data.ndef.flags |= RW_NDEF_FL_FORMATABLE;
432 rw_data.ndef.cur_size = p_i93->ndef_length;
433
434 if (p_i93->intl_flags & RW_I93_FLAG_READ_ONLY) {
435 rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY;
436 rw_data.ndef.max_size = p_i93->ndef_length;
437 } else {
438 rw_data.ndef.flags |= RW_NDEF_FL_HARD_LOCKABLE;
439 /* Assume tag is already in INITIALIZED or READ-WRITE state */
440 p_i93->max_ndef_length =
441 p_i93->t5t_area_last_offset - p_i93->ndef_tlv_start_offset + 1;
442 if (p_i93->max_ndef_length >= 0xFF) {
443 /* 3 bytes length field can be used */
444 p_i93->max_ndef_length -= 4;
445 } else {
446 /* 1 byte length field can be used */
447 p_i93->max_ndef_length -= 2;
448 }
449 rw_data.ndef.max_size = p_i93->max_ndef_length;
450 }
451
452 /* Complete the greedy collection */
453 p_i93->gre_ndef_tlv_pos = p_i93->ndef_tlv_start_offset;
454 p_i93->gre_ndef_tlv_length = p_i93->ndef_length;
455 p_i93->gre_validity = 1;
456 p_i93->state = RW_I93_STATE_IDLE;
457 p_i93->sent_cmd = 0;
458
459 LOG(VERBOSE) << StringPrintf(
460 "%s - NDEF cur_size (%d), max_size (%d), flags (0x%x)", __func__,
461 rw_data.ndef.cur_size, rw_data.ndef.max_size, rw_data.ndef.flags);
462
463 (*(rw_cb.p_cback))(RW_I93_NDEF_DETECT_EVT, &rw_data);
464 break;
465 } else {
466 /* read more data */
467 p_i93->rw_offset += length;
468
469 if (p_i93->rw_offset > p_i93->t5t_area_last_offset) {
470 rw_i93_handle_error(NFC_STATUS_FAILED);
471 } else {
472 if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
473 p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
474 } else {
475 rw_i93_handle_error(NFC_STATUS_FAILED);
476 }
477 }
478 }
479 break;
480
481 default:
482 break;
483 }
484 }
485
486 /*******************************************************************************
487 **
488 ** Function rw_t5t_sm_update_ndef
489 **
490 ** Description Process NDEF update procedure
491 **
492 ** 1. Set length field to zero
493 ** 2. Write NDEF and Terminator TLV
494 ** 3. Set length field to NDEF length
495 **
496 ** Returns void
497 **
498 *******************************************************************************/
rw_t5t_sm_update_ndef(NFC_HDR * p_resp)499 void rw_t5t_sm_update_ndef(NFC_HDR* p_resp) {
500 uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
501 uint8_t flags, xx, buff[I93_MAX_BLOCK_LENGH];
502 uint16_t length_offset;
503 uint16_t length = p_resp->len, block_number;
504 tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
505 tRW_DATA rw_data;
506
507 LOG(VERBOSE) << StringPrintf(
508 "%s - sub_state:%s (0x%x)", __func__,
509 rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
510
511 if (length == 0 || p_i93->block_size > I93_MAX_BLOCK_LENGH) {
512 android_errorWriteLog(0x534e4554, "122320256");
513 rw_i93_handle_error(NFC_STATUS_FAILED);
514 return;
515 }
516
517 STREAM_TO_UINT8(flags, p);
518 length--;
519
520 if (flags & I93_FLAG_ERROR_DETECTED) {
521 LOG(VERBOSE) << StringPrintf("%s - Got error flags (0x%02x)", __func__,
522 flags);
523 rw_i93_handle_error(NFC_STATUS_FAILED);
524 return;
525 }
526
527 switch (p_i93->sub_state) {
528 case RW_I93_SUBSTATE_RESET_LEN:
529
530 /* get offset of length field */
531 length_offset = (p_i93->ndef_tlv_start_offset + 1) % p_i93->block_size;
532
533 if (length < length_offset) {
534 android_errorWriteLog(0x534e4554, "122320256");
535 rw_i93_handle_error(NFC_STATUS_FAILED);
536 return;
537 }
538
539 /* set length to zero */
540 *(p + length_offset) = 0x00;
541
542 if (p_i93->ndef_length > 0) {
543 /* if 3 bytes length field is needed */
544 if (p_i93->ndef_length >= 0xFF) {
545 xx = length_offset + 3;
546 } else {
547 xx = length_offset + 1;
548 }
549
550 if (p_i93->ndef_length >= 0xFF) {
551 p_i93->ndef_tlv_last_offset = p_i93->ndef_tlv_start_offset + 3;
552 } else {
553 p_i93->ndef_tlv_last_offset = p_i93->ndef_tlv_start_offset + 1;
554 }
555
556 /* write the first part of NDEF in the same block */
557 for (; xx < p_i93->block_size; xx++) {
558 if (xx > length || p_i93->rw_length > p_i93->ndef_length) {
559 android_errorWriteLog(0x534e4554, "122320256");
560 rw_i93_handle_error(NFC_STATUS_FAILED);
561 return;
562 }
563 if (p_i93->rw_length < p_i93->ndef_length) {
564 *(p + xx) = *(p_i93->p_update_data + p_i93->rw_length++);
565 p_i93->ndef_tlv_last_offset++;
566 } else {
567 *(p + xx) = I93_ICODE_TLV_TYPE_NULL;
568 }
569 }
570 }
571
572 block_number = (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
573
574 if (rw_i93_send_cmd_write_single_block(block_number, p) ==
575 NFC_STATUS_OK) {
576 /* update next writing offset */
577 p_i93->rw_offset = (block_number + 1) * p_i93->block_size;
578 p_i93->sub_state = RW_I93_SUBSTATE_WRITE_NDEF;
579 } else {
580 rw_i93_handle_error(NFC_STATUS_FAILED);
581 }
582 break;
583
584 case RW_I93_SUBSTATE_WRITE_NDEF:
585
586 /* if it's not the end of tag memory */
587 if (p_i93->rw_offset <= p_i93->t5t_area_last_offset) {
588 // Note: Needed to write in the last block of the memory
589 block_number = p_i93->rw_offset / p_i93->block_size;
590
591 /* if we have more data to write */
592 if (p_i93->rw_length < p_i93->ndef_length) {
593 p = p_i93->p_update_data + p_i93->rw_length;
594
595 p_i93->rw_offset += p_i93->block_size;
596 p_i93->rw_length += p_i93->block_size;
597
598 /* if this is the last block of NDEF TLV */
599 if (p_i93->rw_length >= p_i93->ndef_length) {
600 /* length of NDEF TLV in the block */
601 xx = (uint8_t)(p_i93->block_size -
602 (p_i93->rw_length - p_i93->ndef_length));
603 /* set NULL TLV in the unused part of block */
604 memset(buff, I93_ICODE_TLV_TYPE_NULL, p_i93->block_size);
605 memcpy(buff, p, xx);
606 p = buff;
607
608 /* if it's the end of tag memory */
609 if (((p_i93->rw_offset - p_i93->block_size + xx) <=
610 p_i93->t5t_area_last_offset) &&
611 (xx < p_i93->block_size)) {
612 buff[xx] = I93_ICODE_TLV_TYPE_TERM;
613 }
614 // Note: Needed to write Terminator TLV in block following
615 // the NDEF Message ending in byte 3 of the previous block
616 p_i93->ndef_tlv_last_offset =
617 p_i93->rw_offset - p_i93->block_size + xx - 1;
618
619 } else {
620 p_i93->ndef_tlv_last_offset += p_i93->block_size;
621 }
622
623 if (rw_i93_send_cmd_write_single_block(block_number, p) !=
624 NFC_STATUS_OK) {
625 rw_i93_handle_error(NFC_STATUS_FAILED);
626 }
627 } else {
628 /* if this is the very next block of NDEF TLV */
629 // Note: Needed to write Terminator TLV in block following
630 // the NDEF Message ending in byte 3 of the previous block
631 if ((block_number ==
632 (p_i93->ndef_tlv_last_offset / p_i93->block_size) + 1) &&
633 (((p_i93->ndef_tlv_last_offset + 1) % p_i93->block_size) == 0)) {
634 /* write Terminator TLV and NULL TLV */
635 memset(buff, I93_ICODE_TLV_TYPE_NULL, p_i93->block_size);
636 buff[0] = I93_ICODE_TLV_TYPE_TERM;
637 p = buff;
638
639 if (rw_i93_send_cmd_write_single_block(block_number, p) !=
640 NFC_STATUS_OK) {
641 rw_i93_handle_error(NFC_STATUS_FAILED);
642 }
643
644 block_number =
645 (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
646
647 /* set offset to length field */
648 p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
649
650 /* get size of length field */
651 if (p_i93->ndef_length >= 0xFF) {
652 p_i93->rw_length = 3;
653 } else if (p_i93->ndef_length > 0) {
654 p_i93->rw_length = 1;
655 } else {
656 p_i93->rw_length = 0;
657 }
658 p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
659
660 } else {
661 /* finished writing NDEF and Terminator TLV */
662 /* read length field to update length */
663 block_number =
664 (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
665
666 if (rw_i93_send_cmd_read_single_block(block_number, false) ==
667 NFC_STATUS_OK) {
668 /* set offset to length field */
669 p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
670
671 /* get size of length field */
672 if (p_i93->ndef_length >= 0xFF) {
673 p_i93->rw_length = 3;
674 } else if (p_i93->ndef_length > 0) {
675 p_i93->rw_length = 1;
676 } else {
677 p_i93->rw_length = 0;
678 }
679 p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
680 } else {
681 rw_i93_handle_error(NFC_STATUS_FAILED);
682 }
683 }
684 }
685 } /* (p_i93->rw_offset <= p_i93->t5t_area_last_offset) */
686
687 else {
688 /* if we have no more data to write */
689 if (p_i93->rw_length >= p_i93->ndef_length) {
690 /* finished writing NDEF and Terminator TLV */
691 /* read length field to update length */
692 block_number = (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
693
694 if (rw_i93_send_cmd_read_single_block(block_number, false) ==
695 NFC_STATUS_OK) {
696 /* set offset to length field */
697 p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
698
699 /* get size of length field */
700 if (p_i93->ndef_length >= 0xFF) {
701 p_i93->rw_length = 3;
702 } else if (p_i93->ndef_length > 0) {
703 p_i93->rw_length = 1;
704 } else {
705 p_i93->rw_length = 0;
706 }
707
708 p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
709 break;
710 }
711 }
712 rw_i93_handle_error(NFC_STATUS_FAILED);
713 }
714 break;
715
716 case RW_I93_SUBSTATE_UPDATE_LEN:
717 /* if we have more length field to write */
718 if (p_i93->rw_length > 0) {
719 /* if we got ack for writing, read next block to update rest of length
720 * field */
721 if (length == 0) {
722 block_number = p_i93->rw_offset / p_i93->block_size;
723
724 if (rw_i93_send_cmd_read_single_block(block_number, false) !=
725 NFC_STATUS_OK) {
726 rw_i93_handle_error(NFC_STATUS_FAILED);
727 }
728 } else {
729 length_offset = p_i93->rw_offset % p_i93->block_size;
730
731 /* update length field within the read block */
732 for (xx = length_offset; xx < p_i93->block_size; xx++) {
733 if (xx > length) {
734 android_errorWriteLog(0x534e4554, "122320256");
735 rw_i93_handle_error(NFC_STATUS_FAILED);
736 return;
737 }
738
739 if (p_i93->rw_length == 3)
740 *(p + xx) = 0xFF;
741 else if (p_i93->rw_length == 2)
742 *(p + xx) = (uint8_t)((p_i93->ndef_length >> 8) & 0xFF);
743 else if (p_i93->rw_length == 1)
744 *(p + xx) = (uint8_t)(p_i93->ndef_length & 0xFF);
745
746 p_i93->rw_length--;
747 if (p_i93->rw_length == 0) break;
748 }
749
750 block_number = (p_i93->rw_offset / p_i93->block_size);
751
752 if (rw_i93_send_cmd_write_single_block(block_number, p) ==
753 NFC_STATUS_OK) {
754 /* set offset to the beginning of next block */
755 p_i93->rw_offset +=
756 p_i93->block_size - (p_i93->rw_offset % p_i93->block_size);
757 } else {
758 rw_i93_handle_error(NFC_STATUS_FAILED);
759 }
760 }
761 } else {
762 LOG(VERBOSE) << StringPrintf(
763 "%s - NDEF update complete, %d bytes, (%d-%d)", __func__,
764 p_i93->ndef_length, p_i93->ndef_tlv_start_offset,
765 p_i93->ndef_tlv_last_offset);
766
767 p_i93->state = RW_I93_STATE_IDLE;
768 p_i93->sent_cmd = 0;
769 p_i93->p_update_data = nullptr;
770
771 rw_data.status = NFC_STATUS_OK;
772 (*(rw_cb.p_cback))(RW_I93_NDEF_UPDATE_CPLT_EVT, &rw_data);
773 }
774 break;
775
776 default:
777 break;
778 }
779 }
780
781 /*******************************************************************************
782 **
783 ** Function rw_i93_sm_set_read_only
784 **
785 ** Description Process read-only procedure
786 **
787 ** 1. Update CC as read-only
788 ** 2. Lock all block of NDEF TLV
789 ** 3. Lock block of CC
790 **
791 ** Returns void
792 **
793 *******************************************************************************/
rw_t5t_sm_set_read_only(NFC_HDR * p_resp)794 void rw_t5t_sm_set_read_only(NFC_HDR* p_resp) {
795 uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
796 uint16_t block_number;
797 uint8_t flags;
798
799 uint16_t length = p_resp->len;
800 tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
801 tRW_DATA rw_data;
802
803 LOG(VERBOSE) << StringPrintf(
804 "%s - sub_state:%s (0x%x)", __func__,
805 rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
806
807 if (length == 0) {
808 android_errorWriteLog(0x534e4554, "122322613");
809 rw_i93_handle_error(NFC_STATUS_FAILED);
810 return;
811 }
812
813 STREAM_TO_UINT8(flags, p);
814 length--;
815
816 if (flags & I93_FLAG_ERROR_DETECTED) {
817 LOG(VERBOSE) << StringPrintf("%s - Got error flags (0x%02x)", __func__,
818 flags);
819 rw_i93_handle_error(NFC_STATUS_FAILED);
820 return;
821 }
822
823 switch (p_i93->sub_state) {
824 case RW_I93_SUBSTATE_WAIT_CC:
825
826 if (length < RW_I93_CC_SIZE) {
827 android_errorWriteLog(0x534e4554, "139188579");
828 rw_i93_handle_error(NFC_STATUS_FAILED);
829 return;
830 }
831 /* mark CC as read-only */
832 *(p + 1) |= I93_ICODE_CC_READ_ONLY;
833
834 if (rw_i93_send_cmd_write_single_block(0, p) == NFC_STATUS_OK) {
835 p_i93->sub_state = RW_I93_SUBSTATE_WAIT_UPDATE_CC;
836 } else {
837 rw_i93_handle_error(NFC_STATUS_FAILED);
838 }
839 break;
840
841 case RW_I93_SUBSTATE_WAIT_UPDATE_CC:
842
843 /* successfully write CC then lock CC and all blocks of T5T Area */
844 p_i93->rw_offset = 0;
845
846 if (rw_i93_send_cmd_lock_block(0) == NFC_STATUS_OK) {
847 p_i93->rw_offset += p_i93->block_size;
848 p_i93->sub_state = RW_I93_SUBSTATE_LOCK_T5T_AREA;
849 } else {
850 rw_i93_handle_error(NFC_STATUS_FAILED);
851 }
852 break;
853
854 case RW_I93_SUBSTATE_LOCK_T5T_AREA:
855
856 LOG(VERBOSE) << StringPrintf(
857 "%s - rw_offset:0x%02x, t5t_area_last_offset:0x%02x", __func__,
858 p_i93->rw_offset, p_i93->t5t_area_last_offset);
859
860 /* 2nd block to be locked can be the last 4 bytes of CC in case CC
861 * is 8byte long, then T5T_Area starts */
862 if (p_i93->rw_offset <= p_i93->t5t_area_last_offset) {
863 if (p_i93->block_size == 0) {
864 LOG(ERROR) << StringPrintf("%s - zero block_size error", __func__);
865 rw_i93_handle_error(NFC_STATUS_FAILED);
866 break;
867 }
868 /* get the next block of NDEF TLV */
869 block_number = (uint16_t)(p_i93->rw_offset / p_i93->block_size);
870
871 if (rw_i93_send_cmd_lock_block(block_number) == NFC_STATUS_OK) {
872 p_i93->rw_offset += p_i93->block_size;
873 } else {
874 rw_i93_handle_error(NFC_STATUS_FAILED);
875 }
876 } else {
877 p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
878 p_i93->state = RW_I93_STATE_IDLE;
879 p_i93->sent_cmd = 0;
880
881 rw_data.status = NFC_STATUS_OK;
882 (*(rw_cb.p_cback))(RW_I93_SET_TAG_RO_EVT, &rw_data);
883 }
884 break;
885
886 default:
887 break;
888 }
889 }
890