• 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 <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