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