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