• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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