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