• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-2014 Broadcom Corporation
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 Type 3 tag in Reader/Writer
22  *  mode.
23  *
24  ******************************************************************************/
25 #include <string.h>
26 
27 #include <android-base/stringprintf.h>
28 #include <base/logging.h>
29 #include <log/log.h>
30 
31 #include "nfc_target.h"
32 
33 #include "bt_types.h"
34 #include "nci_hmsgs.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 bool nfc_debug_enabled;
43 
44 /* Definitions for constructing t3t command messages */
45 #define RW_T3T_FL_PADDING 0x01 /* Padding needed for last NDEF block */
46 /* Maximum number of NDEF blocks updates that can fit into one command (when all
47  * block-numbers are < 256) */
48 #define RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_1_BYTE_FORMAT (13)
49 /* Maximum number of NDEF blocks updates that can fit into one command (when all
50  * block-numbers are >= 256) */
51 #define RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_2_BYTE_FORMAT (12)
52 
53 /* Definitions for SENSF_RES */
54 /* Offset of RD in SENSF_RES from NCI_POLL NTF (includes 1 byte SENSF_RES
55  * length) */
56 #define RW_T3T_SENSF_RES_RD_OFFSET 17
57 #define RW_T3T_SENSF_RES_RD_LEN 2 /* Size of RD in SENSF_RES   */
58 
59 /* Timeout definitions for commands */
60 #define RW_T3T_POLL_CMD_TIMEOUT_TICKS \
61   ((RW_T3T_TOUT_RESP * 2 * QUICK_TIMER_TICKS_PER_SEC) / 1000)
62 #define RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS \
63   ((RW_T3T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000)
64 #define RW_T3T_RAW_FRAME_CMD_TIMEOUT_TICKS \
65   (RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * 4)
66 #define RW_T3T_MIN_TIMEOUT_TICKS 10
67 
68 /* Macro to extract major version from NDEF version byte */
69 #define T3T_GET_MAJOR_VERSION(ver) ((ver) >> 4)
70 
71 /* Enumeration of API commands */
72 enum {
73   RW_T3T_CMD_DETECT_NDEF,
74   RW_T3T_CMD_CHECK_NDEF,
75   RW_T3T_CMD_UPDATE_NDEF,
76   RW_T3T_CMD_CHECK,
77   RW_T3T_CMD_UPDATE,
78   RW_T3T_CMD_SEND_RAW_FRAME,
79   RW_T3T_CMD_GET_SYSTEM_CODES,
80   RW_T3T_CMD_FORMAT,
81   RW_T3T_CMD_SET_READ_ONLY_SOFT,
82   RW_T3T_CMD_SET_READ_ONLY_HARD,
83 
84   RW_T3T_CMD_MAX
85 };
86 
87 /* RW_CBACK events corresponding to API comands */
88 const uint8_t rw_t3t_api_res_evt[RW_T3T_CMD_MAX] = {
89     RW_T3T_NDEF_DETECT_EVT,       /* RW_T3T_CMD_DETECT_NDEF */
90     RW_T3T_CHECK_CPLT_EVT,        /* RW_T3T_CMD_CHECK_NDEF  */
91     RW_T3T_UPDATE_CPLT_EVT,       /* RW_T3T_CMD_UPDATE_NDEF */
92     RW_T3T_CHECK_CPLT_EVT,        /* RW_T3T_CMD_CHECK */
93     RW_T3T_UPDATE_CPLT_EVT,       /* RW_T3T_CMD_UPDATE */
94     RW_T3T_RAW_FRAME_EVT,         /* RW_T3T_CMD_SEND_RAW_FRAME */
95     RW_T3T_GET_SYSTEM_CODES_EVT,  /* RW_T3T_CMD_GET_SYSTEM_CODES */
96     RW_T3T_FORMAT_CPLT_EVT,       /* RW_T3T_CMD_FORMAT */
97     RW_T3T_SET_READ_ONLY_CPLT_EVT /* RW_T3T_CMD_SET_READ_ONLY */
98 };
99 
100 /* States */
101 enum {
102   RW_T3T_STATE_NOT_ACTIVATED,
103   RW_T3T_STATE_IDLE,
104   RW_T3T_STATE_COMMAND_PENDING
105 };
106 
107 /* Sub-states */
108 enum {
109   /* Sub states for formatting Felica-Lite */
110   RW_T3T_FMT_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
111                                       formatting) */
112   RW_T3T_FMT_SST_CHECK_MC_BLK,     /* Waiting for Felica-Lite MC (MemoryControl)
113                                       block-read to complete */
114   RW_T3T_FMT_SST_UPDATE_MC_BLK,    /* Waiting for Felica-Lite MC (MemoryControl)
115                                       block-write to complete */
116   RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
117                                         to complete */
118 
119   /* Sub states for setting Felica-Lite read only */
120   RW_T3T_SRO_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
121                                       setting read only) */
122   RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
123                                         to complete */
124   RW_T3T_SRO_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
125                                   block-read to complete */
126   RW_T3T_SRO_SST_UPDATE_MC_BLK /* Waiting for Felica-Lite MC (MemoryControl)
127                                   block-write to complete */
128 };
129 
130 static std::string rw_t3t_cmd_str(uint8_t cmd_id);
131 static std::string rw_t3t_state_str(uint8_t state_id);
132 
133 /* Local static functions */
134 static void rw_t3t_update_ndef_flag(uint8_t* p_flag);
135 static tNFC_STATUS rw_t3t_unselect();
136 static NFC_HDR* rw_t3t_get_cmd_buf(void);
137 static tNFC_STATUS rw_t3t_send_to_lower(NFC_HDR* p_msg);
138 static void rw_t3t_handle_get_system_codes_cplt(void);
139 static void rw_t3t_handle_get_sc_poll_rsp(tRW_T3T_CB* p_cb, uint8_t nci_status,
140                                           uint8_t num_responses,
141                                           uint8_t sensf_res_buf_size,
142                                           uint8_t* p_sensf_res_buf);
143 static void rw_t3t_handle_ndef_detect_poll_rsp(tRW_T3T_CB* p_cb,
144                                                uint8_t nci_status,
145                                                uint8_t num_responses);
146 static void rw_t3t_handle_fmt_poll_rsp(tRW_T3T_CB* p_cb, uint8_t nci_status,
147                                        uint8_t num_responses);
148 static void rw_t3t_handle_sro_poll_rsp(tRW_T3T_CB* p_cb, uint8_t nci_status,
149                                        uint8_t num_responses);
150 
151 /* Default NDEF attribute information block (used when formatting Felica-Lite
152  * tags) */
153 /* NBr (max block reads per cmd)*/
154 #define RW_T3T_DEFAULT_FELICALITE_NBR 4
155 /* NBw (max block write per cmd)*/
156 #define RW_T3T_DEFAULT_FELICALITE_NBW 1
157 #define RW_T3T_DEFAULT_FELICALITE_NMAXB (T3T_FELICALITE_NMAXB)
158 #define RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM                       \
159   ((T3T_MSG_NDEF_VERSION + RW_T3T_DEFAULT_FELICALITE_NBR +                   \
160     RW_T3T_DEFAULT_FELICALITE_NBW + (RW_T3T_DEFAULT_FELICALITE_NMAXB >> 8) + \
161     (RW_T3T_DEFAULT_FELICALITE_NMAXB & 0xFF) + T3T_MSG_NDEF_WRITEF_OFF +     \
162     T3T_MSG_NDEF_RWFLAG_RW) &                                                \
163    0xFFFF)
164 
165 const uint8_t rw_t3t_default_attrib_info[T3T_MSG_BLOCKSIZE] = {
166     T3T_MSG_NDEF_VERSION,                     /* Ver                          */
167     RW_T3T_DEFAULT_FELICALITE_NBR,            /* NBr (max block reads per cmd)*/
168     RW_T3T_DEFAULT_FELICALITE_NBW,            /* NBw (max block write per cmd)*/
169     (RW_T3T_DEFAULT_FELICALITE_NMAXB >> 8),   /* Nmaxb (max size in blocks)   */
170     (RW_T3T_DEFAULT_FELICALITE_NMAXB & 0xFF), /* Nmaxb (max size in blocks)   */
171     0, 0, 0, 0,                               /* Unused                       */
172     T3T_MSG_NDEF_WRITEF_OFF,                  /* WriteF                       */
173     T3T_MSG_NDEF_RWFLAG_RW,                   /* RW Flag                      */
174     0, 0, 0,                                  /* Ln (current size in bytes)   */
175 
176     (RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM >>
177      8), /* checksum (high-byte) */
178     (RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM &
179      0xFF) /* checksum (low-byte)  */
180 
181 };
182 
183 /* This is (T/t3t * 4^E) , E is the index of the array. The unit is .0001 ms */
184 static const uint32_t rw_t3t_mrti_base[] = {302, 1208, 4832, 19328};
185 
186 /*******************************************************************************
187 **
188 ** Function         rw_t3t_check_timeout
189 **
190 ** Description      The timeout value is a + b * number_blocks)
191 **
192 ** Returns          timeout value in ticks
193 **
194 *******************************************************************************/
rw_t3t_check_timeout(uint16_t num_blocks)195 static uint32_t rw_t3t_check_timeout(uint16_t num_blocks) {
196   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
197   uint32_t timeout;
198   uint32_t extra;
199 
200   timeout = (p_cb->check_tout_a + num_blocks * p_cb->check_tout_b) *
201             QUICK_TIMER_TICKS_PER_SEC / 1000000;
202   /* allow some extra time for driver */
203   extra = (timeout / 10) + RW_T3T_MIN_TIMEOUT_TICKS;
204   timeout += extra;
205 
206   return timeout;
207 }
208 
209 /*******************************************************************************
210 **
211 ** Function         rw_t3t_update_timeout
212 **
213 ** Description      The timeout value is a + b * number_blocks)
214 **
215 ** Returns          timeout value in ticks
216 **
217 *******************************************************************************/
rw_t3t_update_timeout(uint16_t num_blocks)218 static uint32_t rw_t3t_update_timeout(uint16_t num_blocks) {
219   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
220   uint32_t timeout;
221   uint32_t extra;
222 
223   timeout = (p_cb->update_tout_a + num_blocks * p_cb->update_tout_b) *
224             QUICK_TIMER_TICKS_PER_SEC / 1000000;
225   /* allow some extra time for driver */
226   extra = (timeout / 10) + RW_T3T_MIN_TIMEOUT_TICKS;
227   timeout += extra;
228 
229   return timeout;
230 }
231 /*******************************************************************************
232 **
233 ** Function         rw_t3t_process_error
234 **
235 ** Description      Process error (timeout or CRC error)
236 **
237 ** Returns          none
238 **
239 *******************************************************************************/
rw_t3t_process_error(tNFC_STATUS status)240 void rw_t3t_process_error(tNFC_STATUS status) {
241   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
242   uint8_t evt;
243   tRW_DATA evt_data;
244   NFC_HDR* p_cmd_buf;
245 
246   if (p_cb->rw_state == RW_T3T_STATE_COMMAND_PENDING) {
247     if (p_cb->cur_cmd == RW_T3T_CMD_GET_SYSTEM_CODES) {
248       /* For GetSystemCode: tag did not respond to requested POLL */
249       rw_t3t_handle_get_system_codes_cplt();
250       return;
251     } else if ((p_cb->flags & (RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP |
252                                RW_T3T_FL_W4_GET_SC_POLL_RSP |
253                                RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP |
254                                RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP |
255                                RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP |
256                                RW_T3T_FL_W4_USER_POLL_RSP))) {
257       /* Tag did not respond correctly to requested POLL */
258       return;
259     }
260     /* Retry sending command if retry-count < max */
261     else if (rw_cb.cur_retry < RW_MAX_RETRIES) {
262       /* retry sending the command */
263       rw_cb.cur_retry++;
264 
265       DLOG_IF(INFO, nfc_debug_enabled)
266           << StringPrintf("T3T retransmission attempt %i of %i",
267                           rw_cb.cur_retry, RW_MAX_RETRIES);
268 
269       /* allocate a new buffer for message */
270       p_cmd_buf = rw_t3t_get_cmd_buf();
271       if (p_cmd_buf != nullptr) {
272         memcpy(p_cmd_buf, p_cb->p_cur_cmd_buf, sizeof(NFC_HDR) +
273                                                    p_cb->p_cur_cmd_buf->offset +
274                                                    p_cb->p_cur_cmd_buf->len);
275 
276         if (rw_t3t_send_to_lower(p_cmd_buf) == NFC_STATUS_OK) {
277           /* Start timer for waiting for response */
278           nfc_start_quick_timer(&p_cb->timer, NFC_TTYPE_RW_T3T_RESPONSE,
279                                 p_cb->cur_tout);
280           return;
281         } else {
282           android_errorWriteLog(0x534e4554, "179687208");
283         }
284       }
285     } else {
286       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
287           "T3T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES);
288     }
289 
290 #if (RW_STATS_INCLUDED == TRUE)
291     /* update failure count */
292     rw_main_update_fail_stats();
293 #endif /* RW_STATS_INCLUDED */
294 
295     p_cb->rw_state = RW_T3T_STATE_IDLE;
296 
297     /* Notify app of result (if there was a pending command) */
298     if (p_cb->cur_cmd < RW_T3T_CMD_MAX) {
299       /* If doing presence check, use status=NFC_STATUS_FAILED, otherwise
300        * NFC_STATUS_TIMEOUT */
301       evt_data.status = status;
302       if (rw_cb.cur_retry < RW_MAX_RETRIES)
303         evt = rw_t3t_api_res_evt[p_cb->cur_cmd];
304       else
305         evt = RW_T3T_INTF_ERROR_EVT;
306 
307       /* Set additional flags for RW_T3T_NDEF_DETECT_EVT */
308       if (evt == RW_T3T_NDEF_DETECT_EVT) {
309         evt_data.ndef.flags = RW_NDEF_FL_UNKNOWN;
310         rw_t3t_update_ndef_flag(&evt_data.ndef.flags);
311       }
312 
313       (*(rw_cb.p_cback))(evt, &evt_data);
314     }
315   } else {
316     evt_data.status = status;
317     (*(rw_cb.p_cback))(RW_T3T_INTF_ERROR_EVT, &evt_data);
318   }
319 }
320 
321 /*******************************************************************************
322 **
323 ** Function         rw_t3t_start_poll_timer
324 **
325 ** Description      Start the timer for T3T POLL Command
326 **
327 ** Returns          none
328 **
329 *******************************************************************************/
rw_t3t_start_poll_timer(tRW_T3T_CB * p_cb)330 void rw_t3t_start_poll_timer(tRW_T3T_CB* p_cb) {
331   nfc_start_quick_timer(&p_cb->poll_timer, NFC_TTYPE_RW_T3T_RESPONSE,
332                         RW_T3T_POLL_CMD_TIMEOUT_TICKS);
333 }
334 
335 /*******************************************************************************
336 **
337 ** Function         rw_t3t_handle_nci_poll_ntf
338 **
339 ** Description      Handle NCI_T3T_POLLING_NTF
340 **
341 ** Returns          none
342 **
343 *******************************************************************************/
rw_t3t_handle_nci_poll_ntf(uint8_t nci_status,uint8_t num_responses,uint8_t sensf_res_buf_size,uint8_t * p_sensf_res_buf)344 void rw_t3t_handle_nci_poll_ntf(uint8_t nci_status, uint8_t num_responses,
345                                 uint8_t sensf_res_buf_size,
346                                 uint8_t* p_sensf_res_buf) {
347   tRW_DATA evt_data;
348   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
349 
350   /* stop timer for poll response */
351   nfc_stop_quick_timer(&p_cb->poll_timer);
352 
353   /* Stop t3t timer (if started) */
354   if (p_cb->flags & RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP) {
355     p_cb->flags &= ~RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
356     evt_data.status = nci_status;
357     p_cb->rw_state = RW_T3T_STATE_IDLE;
358     (*(rw_cb.p_cback))(RW_T3T_PRESENCE_CHECK_EVT, &evt_data);
359   } else if (p_cb->flags & RW_T3T_FL_W4_GET_SC_POLL_RSP) {
360     /* Handle POLL ntf in response to get system codes */
361     p_cb->flags &= ~RW_T3T_FL_W4_GET_SC_POLL_RSP;
362     rw_t3t_handle_get_sc_poll_rsp(p_cb, nci_status, num_responses,
363                                   sensf_res_buf_size, p_sensf_res_buf);
364   } else if (p_cb->flags & RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP) {
365     /* Handle POLL ntf in response to get system codes */
366     p_cb->flags &= ~RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP;
367     rw_t3t_handle_fmt_poll_rsp(p_cb, nci_status, num_responses);
368   } else if (p_cb->flags & RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP) {
369     /* Handle POLL ntf in response to get system codes */
370     p_cb->flags &= ~RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP;
371     rw_t3t_handle_sro_poll_rsp(p_cb, nci_status, num_responses);
372   } else if (p_cb->flags & RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP) {
373     /* Handle POLL ntf in response to ndef detection */
374     p_cb->flags &= ~RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP;
375     rw_t3t_handle_ndef_detect_poll_rsp(p_cb, nci_status, num_responses);
376   } else {
377     /* Handle POLL ntf in response to RW_T3tPoll */
378     p_cb->flags &= ~RW_T3T_FL_W4_USER_POLL_RSP;
379     evt_data.t3t_poll.status = nci_status;
380     if (evt_data.t3t_poll.status == NCI_STATUS_OK) {
381       evt_data.t3t_poll.rc = p_cb->cur_poll_rc;
382       evt_data.t3t_poll.response_num = num_responses;
383       evt_data.t3t_poll.response_bufsize = sensf_res_buf_size;
384       evt_data.t3t_poll.response_buf = p_sensf_res_buf;
385     }
386 
387     p_cb->rw_state = RW_T3T_STATE_IDLE;
388     (*(rw_cb.p_cback))(RW_T3T_POLL_EVT, &evt_data);
389   }
390 }
391 
392 /*******************************************************************************
393 **
394 ** Function         rw_t3t_handle_get_system_codes_cplt
395 **
396 ** Description      Notify upper layer of system codes
397 **
398 ** Returns          none
399 **
400 *******************************************************************************/
rw_t3t_handle_get_system_codes_cplt(void)401 void rw_t3t_handle_get_system_codes_cplt(void) {
402   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
403   tRW_DATA evt_data;
404   uint8_t i;
405 
406   evt_data.t3t_sc.status = NFC_STATUS_OK;
407   evt_data.t3t_sc.num_system_codes = p_cb->num_system_codes;
408   evt_data.t3t_sc.p_system_codes = p_cb->system_codes;
409 
410   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
411       "number of systems: %i", evt_data.t3t_sc.num_system_codes);
412   for (i = 0; i < evt_data.t3t_sc.num_system_codes; i++) {
413     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
414         "system %i: %04X", i, evt_data.t3t_sc.p_system_codes[i]);
415   }
416 
417   p_cb->rw_state = RW_T3T_STATE_IDLE;
418   (*(rw_cb.p_cback))(RW_T3T_GET_SYSTEM_CODES_EVT, &evt_data);
419 }
420 
421 /*******************************************************************************
422 **
423 ** Function         rw_t3t_format_cplt
424 **
425 ** Description      Notify upper layer of format complete
426 **
427 ** Returns          none
428 **
429 *******************************************************************************/
rw_t3t_format_cplt(tNFC_STATUS status)430 void rw_t3t_format_cplt(tNFC_STATUS status) {
431   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
432   tRW_DATA evt_data;
433 
434   p_cb->rw_state = RW_T3T_STATE_IDLE;
435 
436   /* Update ndef info */
437   p_cb->ndef_attrib.status = status;
438   if (status == NFC_STATUS_OK) {
439     p_cb->ndef_attrib.version = T3T_MSG_NDEF_VERSION;
440     p_cb->ndef_attrib.nbr = RW_T3T_DEFAULT_FELICALITE_NBR;
441     p_cb->ndef_attrib.nbw = RW_T3T_DEFAULT_FELICALITE_NBW;
442     p_cb->ndef_attrib.nmaxb = RW_T3T_DEFAULT_FELICALITE_NMAXB;
443     p_cb->ndef_attrib.writef = T3T_MSG_NDEF_WRITEF_OFF;
444     p_cb->ndef_attrib.rwflag = T3T_MSG_NDEF_RWFLAG_RW;
445     p_cb->ndef_attrib.ln = 0;
446   }
447 
448   /* Notify upper layer of format complete */
449   evt_data.status = status;
450   (*(rw_cb.p_cback))(RW_T3T_FORMAT_CPLT_EVT, &evt_data);
451 }
452 
453 /*******************************************************************************
454 **
455 ** Function         rw_t3t_set_readonly_cplt
456 **
457 ** Description      Notify upper layer of set read only complete
458 **
459 ** Returns          none
460 **
461 *******************************************************************************/
rw_t3t_set_readonly_cplt(tNFC_STATUS status)462 void rw_t3t_set_readonly_cplt(tNFC_STATUS status) {
463   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
464   tRW_DATA evt_data;
465 
466   p_cb->rw_state = RW_T3T_STATE_IDLE;
467 
468   /* Notify upper layer of format complete */
469   evt_data.status = status;
470   (*(rw_cb.p_cback))(RW_T3T_SET_READ_ONLY_CPLT_EVT, &evt_data);
471 }
472 
473 /*******************************************************************************
474 **
475 ** Function         rw_t3t_process_timeout
476 **
477 ** Description      Process timeout
478 **
479 ** Returns          none
480 **
481 *******************************************************************************/
rw_t3t_process_timeout(TIMER_LIST_ENT * p_tle)482 void rw_t3t_process_timeout(TIMER_LIST_ENT* p_tle) {
483   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
484   tRW_DATA evt_data;
485 
486   /* Check which timer timed out */
487   if (p_tle == &p_cb->timer) {
488 /* UPDATE/CHECK response timeout */
489 LOG(ERROR) << StringPrintf("T3T timeout. state=%s cur_cmd=0x%02X (%s)",
490                            rw_t3t_state_str(rw_cb.tcb.t3t.rw_state).c_str(),
491                            rw_cb.tcb.t3t.cur_cmd,
492                            rw_t3t_cmd_str(rw_cb.tcb.t3t.cur_cmd).c_str());
493 
494 rw_t3t_process_error(NFC_STATUS_TIMEOUT);
495   } else {
496     LOG(ERROR) << StringPrintf("T3T POLL timeout.");
497 
498     /* POLL response timeout */
499     if (p_cb->flags & RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP) {
500       /* POLL timeout for presence check */
501       p_cb->flags &= ~RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
502       evt_data.status = NFC_STATUS_FAILED;
503       p_cb->rw_state = RW_T3T_STATE_IDLE;
504       (*(rw_cb.p_cback))(RW_T3T_PRESENCE_CHECK_EVT, &evt_data);
505     } else if (p_cb->flags & RW_T3T_FL_W4_GET_SC_POLL_RSP) {
506       /* POLL timeout for getting system codes */
507       p_cb->flags &= ~RW_T3T_FL_W4_GET_SC_POLL_RSP;
508       rw_t3t_handle_get_system_codes_cplt();
509     } else if (p_cb->flags & RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP) {
510       /* POLL timeout for formatting Felica Lite */
511       p_cb->flags &= ~RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP;
512       LOG(ERROR) << StringPrintf("Felica-Lite tag not detected");
513       rw_t3t_format_cplt(NFC_STATUS_FAILED);
514     } else if (p_cb->flags & RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP) {
515       /* POLL timeout for configuring Felica Lite read only */
516       p_cb->flags &= ~RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP;
517       LOG(ERROR) << StringPrintf("Felica-Lite tag not detected");
518       rw_t3t_set_readonly_cplt(NFC_STATUS_FAILED);
519     } else if (p_cb->flags & RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP) {
520       /* POLL timeout for ndef detection */
521       p_cb->flags &= ~RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP;
522       rw_t3t_handle_ndef_detect_poll_rsp(p_cb, NFC_STATUS_TIMEOUT, 0);
523     } else {
524       /* Timeout waiting for response for RW_T3tPoll */
525       evt_data.t3t_poll.status = NFC_STATUS_FAILED;
526       p_cb->rw_state = RW_T3T_STATE_IDLE;
527       (*(rw_cb.p_cback))(RW_T3T_POLL_EVT, &evt_data);
528     }
529   }
530 }
531 
532 /*******************************************************************************
533 **
534 ** Function         rw_t3t_process_frame_error
535 **
536 ** Description      Process frame crc error
537 **
538 ** Returns          none
539 **
540 *******************************************************************************/
rw_t3t_process_frame_error(void)541 void rw_t3t_process_frame_error(void) {
542   LOG(ERROR) << StringPrintf("T3T frame error. state=%s cur_cmd=0x%02X (%s)",
543                              rw_t3t_state_str(rw_cb.tcb.t3t.rw_state).c_str(),
544                              rw_cb.tcb.t3t.cur_cmd,
545                              rw_t3t_cmd_str(rw_cb.tcb.t3t.cur_cmd).c_str());
546 
547 #if (RW_STATS_INCLUDED == TRUE)
548   /* Update stats */
549   rw_main_update_crc_error_stats();
550 #endif /* RW_STATS_INCLUDED */
551 
552   /* Process the error */
553   rw_t3t_process_error(NFC_STATUS_MSG_CORRUPTED);
554 }
555 
556 /*******************************************************************************
557 **
558 ** Function         rw_t3t_send_to_lower
559 **
560 ** Description      Send command to lower layer
561 **
562 ** Returns          status of the send
563 **
564 *******************************************************************************/
rw_t3t_send_to_lower(NFC_HDR * p_msg)565 tNFC_STATUS rw_t3t_send_to_lower(NFC_HDR* p_msg) {
566   uint8_t* p;
567 
568 #if (RW_STATS_INCLUDED == TRUE)
569   bool is_retry;
570   /* Update stats */
571   rw_main_update_tx_stats(p_msg->len, ((rw_cb.cur_retry == 0) ? false : true));
572 #endif /* RW_STATS_INCLUDED */
573 
574   /* Set NFC-F SoD field (payload len + 1) */
575   if (p_msg->offset) p_msg->offset -= 1; /* Point to SoD field */
576   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
577   UINT8_TO_STREAM(p, (p_msg->len + 1));
578   p_msg->len += 1; /* Increment len to include SoD */
579 
580   return (NFC_SendData(NFC_RF_CONN_ID, p_msg));
581 }
582 
583 /*****************************************************************************
584 **
585 ** Function         rw_t3t_get_cmd_buf
586 **
587 ** Description      Get a buffer for sending T3T messages
588 **
589 ** Returns          NFC_HDR *
590 **
591 *****************************************************************************/
rw_t3t_get_cmd_buf(void)592 NFC_HDR* rw_t3t_get_cmd_buf(void) {
593   NFC_HDR* p_cmd_buf;
594 
595   p_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
596   if (p_cmd_buf != nullptr) {
597     /* Reserve offset for NCI_DATA_HDR and NFC-F Sod (LEN) field */
598     p_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + 1;
599     p_cmd_buf->len = 0;
600   }
601 
602   return (p_cmd_buf);
603 }
604 
605 /*****************************************************************************
606 **
607 ** Function         rw_t3t_send_cmd
608 **
609 ** Description      Send command to tag, and start timer for response
610 **
611 ** Returns          tNFC_STATUS
612 **
613 *****************************************************************************/
rw_t3t_send_cmd(tRW_T3T_CB * p_cb,uint8_t rw_t3t_cmd,NFC_HDR * p_cmd_buf,uint32_t timeout_ticks)614 tNFC_STATUS rw_t3t_send_cmd(tRW_T3T_CB* p_cb, uint8_t rw_t3t_cmd,
615                             NFC_HDR* p_cmd_buf, uint32_t timeout_ticks) {
616   tNFC_STATUS retval;
617 
618   /* Indicate first attempt to send command, back up cmd buffer in case needed
619    * for retransmission */
620   rw_cb.cur_retry = 0;
621   memcpy(p_cb->p_cur_cmd_buf, p_cmd_buf,
622          sizeof(NFC_HDR) + p_cmd_buf->offset + p_cmd_buf->len);
623 
624   p_cb->cur_cmd = rw_t3t_cmd;
625   p_cb->cur_tout = timeout_ticks;
626   p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
627 
628   retval = rw_t3t_send_to_lower(p_cmd_buf);
629   if (retval == NFC_STATUS_OK) {
630     /* Start timer for waiting for response */
631     nfc_start_quick_timer(&p_cb->timer, NFC_TTYPE_RW_T3T_RESPONSE,
632                           timeout_ticks);
633   } else {
634     /* Error sending */
635     p_cb->rw_state = RW_T3T_STATE_IDLE;
636   }
637 
638   DLOG_IF(INFO, nfc_debug_enabled)
639       << StringPrintf("cur_tout: %d, timeout_ticks: %d ret:%d", p_cb->cur_tout,
640                       timeout_ticks, retval);
641   return (retval);
642 }
643 
644 /*****************************************************************************
645 **
646 ** Function         rw_t3t_send_update_ndef_attribute_cmd
647 **
648 ** Description      Send UPDATE command for Attribute Information
649 **
650 ** Returns          tNFC_STATUS
651 **
652 *****************************************************************************/
rw_t3t_send_update_ndef_attribute_cmd(tRW_T3T_CB * p_cb,bool write_in_progress)653 tNFC_STATUS rw_t3t_send_update_ndef_attribute_cmd(tRW_T3T_CB* p_cb,
654                                                   bool write_in_progress) {
655   tNFC_STATUS retval = NFC_STATUS_OK;
656   NFC_HDR* p_cmd_buf;
657   uint8_t *p_cmd_start, *p;
658   uint16_t checksum, i;
659   uint8_t write_f;
660   uint32_t ln;
661   uint8_t* p_ndef_attr_info_start;
662 
663   p_cmd_buf = rw_t3t_get_cmd_buf();
664   if (p_cmd_buf != nullptr) {
665     /* Construct T3T message */
666     p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
667 
668     /* Add UPDATE opcode to message  */
669     UINT8_TO_STREAM(p, T3T_MSG_OPC_UPDATE_CMD);
670 
671     /* Add IDm to message */
672     ARRAY_TO_STREAM(p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
673 
674     /* Add Service code list */
675     UINT8_TO_STREAM(p, 1); /* Number of services (only 1 service: NDEF) */
676     UINT16_TO_STREAM(
677         p, T3T_MSG_NDEF_SC_RW); /* Service code (little-endian format) */
678 
679     /* Add number of blocks in this UPDATE command */
680     UINT8_TO_STREAM(p, 1); /* Number of blocks to write in this command */
681 
682     /* Block List element: the NDEF attribute information block (block 0) */
683     UINT8_TO_STREAM(p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
684     UINT8_TO_STREAM(p, 0);
685 
686     /* Add payload (Attribute information block) */
687     p_ndef_attr_info_start =
688         p; /* Save start of a NDEF attribute info block for checksum */
689     UINT8_TO_STREAM(p, T3T_MSG_NDEF_VERSION);
690     UINT8_TO_STREAM(p, p_cb->ndef_attrib.nbr);
691     UINT8_TO_STREAM(p, p_cb->ndef_attrib.nbw);
692     UINT16_TO_BE_STREAM(p, p_cb->ndef_attrib.nmaxb);
693     UINT32_TO_STREAM(p, 0);
694 
695     /* If starting NDEF write: set WriteF=ON, and ln=current ndef length */
696     if (write_in_progress) {
697       write_f = T3T_MSG_NDEF_WRITEF_ON;
698       ln = p_cb->ndef_attrib.ln;
699     }
700     /* If finishing NDEF write: set WriteF=OFF, and ln=new ndef len */
701     else {
702       write_f = T3T_MSG_NDEF_WRITEF_OFF;
703       ln = p_cb->ndef_msg_len;
704     }
705     UINT8_TO_STREAM(p, write_f);
706     UINT8_TO_STREAM(p, p_cb->ndef_attrib.rwflag);
707     UINT8_TO_STREAM(p, (ln >> 16) & 0xFF); /* High byte (of 3) of Ln */
708     UINT8_TO_STREAM(p, (ln >> 8) & 0xFF);  /* Middle byte (of 3) of Ln */
709     UINT8_TO_STREAM(p, (ln)&0xFF);         /* Low byte (of 3) of Ln */
710 
711     /* Calculate and append Checksum */
712     checksum = 0;
713     for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) {
714       checksum += p_ndef_attr_info_start[i];
715     }
716     UINT16_TO_BE_STREAM(p, checksum);
717 
718     /* Calculate length of message */
719     p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
720 
721     /* Send the T3T message */
722     retval = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_UPDATE_NDEF, p_cmd_buf,
723                              rw_t3t_update_timeout(1));
724   } else {
725     retval = NFC_STATUS_NO_BUFFERS;
726   }
727 
728   return (retval);
729 }
730 
731 /*****************************************************************************
732 **
733 ** Function         rw_t3t_send_next_ndef_update_cmd
734 **
735 ** Description      Send next segment of NDEF message to update
736 **
737 ** Returns          tNFC_STATUS
738 **
739 *****************************************************************************/
rw_t3t_send_next_ndef_update_cmd(tRW_T3T_CB * p_cb)740 tNFC_STATUS rw_t3t_send_next_ndef_update_cmd(tRW_T3T_CB* p_cb) {
741   tNFC_STATUS retval = NFC_STATUS_OK;
742   uint16_t block_id;
743   uint16_t first_block_to_write;
744   uint16_t ndef_blocks_to_write, ndef_blocks_remaining;
745   uint32_t ndef_bytes_remaining, ndef_padding = 0;
746   uint8_t flags = 0;
747   uint8_t* p_cur_ndef_src_offset;
748   NFC_HDR* p_cmd_buf;
749   uint8_t *p_cmd_start, *p;
750   uint8_t blocks_per_update;
751   uint32_t timeout;
752 
753   p_cmd_buf = rw_t3t_get_cmd_buf();
754   if (p_cmd_buf != nullptr) {
755     /* Construct T3T message */
756     p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
757 
758     /* Calculate number of ndef bytes remaining to write */
759     ndef_bytes_remaining = p_cb->ndef_msg_len - p_cb->ndef_msg_bytes_sent;
760 
761     /* Calculate number of blocks remaining to write */
762     ndef_blocks_remaining =
763         (uint16_t)((ndef_bytes_remaining + 15) >>
764                    4); /* ndef blocks remaining (rounded upward) */
765 
766     /* Calculate first NDEF block ID for this UPDATE command */
767     first_block_to_write = (uint16_t)((p_cb->ndef_msg_bytes_sent >> 4) + 1);
768 
769     /* Calculate max number of blocks per write. */
770     if ((first_block_to_write +
771          RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_1_BYTE_FORMAT) < 0x100) {
772       /* All block-numbers are < 0x100 (i.e. can be specified using one-byte
773        * format) */
774       blocks_per_update = RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_1_BYTE_FORMAT;
775     } else {
776       /* Block-numbers are >= 0x100 (i.e. need to be specified using two-byte
777        * format) */
778       blocks_per_update = RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_2_BYTE_FORMAT;
779     }
780 
781     /* Check if blocks_per_update is bigger than what peer allows */
782     if (blocks_per_update > p_cb->ndef_attrib.nbw)
783       blocks_per_update = p_cb->ndef_attrib.nbw;
784 
785     /* Check if remaining blocks can fit into one UPDATE command */
786     if (ndef_blocks_remaining <= blocks_per_update) {
787       /* remaining blocks can fit into one UPDATE command */
788       ndef_blocks_to_write = ndef_blocks_remaining;
789     } else {
790       /* Remaining blocks cannot fit into one UPDATE command */
791       ndef_blocks_to_write = blocks_per_update;
792     }
793 
794     /* Write to command header for UPDATE */
795 
796     /* Add UPDATE opcode to message  */
797     UINT8_TO_STREAM(p, T3T_MSG_OPC_UPDATE_CMD);
798 
799     /* Add IDm to message */
800     ARRAY_TO_STREAM(p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
801 
802     /* Add Service code list */
803     UINT8_TO_STREAM(p, 1); /* Number of services (only 1 service: NDEF) */
804     UINT16_TO_STREAM(
805         p, T3T_MSG_NDEF_SC_RW); /* Service code (little-endian format) */
806 
807     /* Add number of blocks in this UPDATE command */
808     UINT8_TO_STREAM(
809         p,
810         ndef_blocks_to_write); /* Number of blocks to write in this command */
811     timeout = rw_t3t_update_timeout(ndef_blocks_to_write);
812 
813     for (block_id = first_block_to_write;
814          block_id < (first_block_to_write + ndef_blocks_to_write); block_id++) {
815       if (block_id < 256) {
816         /* Block IDs 0-255 can be specified in '2-byte' format: byte0=0,
817          * byte1=blocknumber */
818         UINT8_TO_STREAM(
819             p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT); /* byte0: len=1;
820                                                             access-mode=0;
821                                                             service code list
822                                                             order=0 */
823         UINT8_TO_STREAM(p, block_id); /* byte1: block number */
824       } else {
825         /* Block IDs 256+ must be specified in '3-byte' format: byte0=80h,
826          * followed by blocknumber */
827         UINT8_TO_STREAM(
828             p,
829             0x00); /* byte0: len=0; access-mode=0; service code list order=0 */
830         UINT16_TO_STREAM(
831             p, block_id); /* byte1-2: block number in little-endian format */
832       }
833     }
834 
835     /* Add NDEF payload */
836 
837     /* If this sending last block of NDEF,  check if padding is needed to make
838      * payload a multiple of 16 bytes */
839     if (ndef_blocks_to_write == ndef_blocks_remaining) {
840       ndef_padding = (16 - (ndef_bytes_remaining & 0x0F)) & 0x0F;
841       if (ndef_padding) {
842         flags |= RW_T3T_FL_PADDING;
843         ndef_blocks_to_write--; /* handle the last block separately if it needs
844                                    padding */
845       }
846     }
847 
848     /* Add NDEF payload to the message */
849     p_cur_ndef_src_offset = &p_cb->ndef_msg[p_cb->ndef_msg_bytes_sent];
850 
851     ARRAY_TO_STREAM(p, p_cur_ndef_src_offset, (ndef_blocks_to_write * 16));
852     p_cb->ndef_msg_bytes_sent += ((uint32_t)ndef_blocks_to_write * 16);
853 
854     if (flags & RW_T3T_FL_PADDING) {
855       /* Add last of the NDEF message */
856       p_cur_ndef_src_offset = &p_cb->ndef_msg[p_cb->ndef_msg_bytes_sent];
857       ARRAY_TO_STREAM(p, p_cur_ndef_src_offset, (int)(16 - ndef_padding));
858       p_cb->ndef_msg_bytes_sent += (16 - ndef_padding);
859 
860       /* Add padding */
861       memset(p, 0, ndef_padding);
862       p += ndef_padding;
863     }
864 
865     /* Calculate length of message */
866     p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
867 
868     /* Send the T3T message */
869     retval = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_UPDATE_NDEF, p_cmd_buf, timeout);
870   } else {
871     retval = NFC_STATUS_NO_BUFFERS;
872   }
873 
874   return (retval);
875 }
876 
877 /*****************************************************************************
878 **
879 ** Function         rw_t3t_send_next_ndef_check_cmd
880 **
881 ** Description      Send command for reading next segment of NDEF message
882 **
883 ** Returns          tNFC_STATUS
884 **
885 *****************************************************************************/
rw_t3t_send_next_ndef_check_cmd(tRW_T3T_CB * p_cb)886 tNFC_STATUS rw_t3t_send_next_ndef_check_cmd(tRW_T3T_CB* p_cb) {
887   tNFC_STATUS retval = NFC_STATUS_OK;
888   uint16_t block_id;
889   uint16_t ndef_blocks_remaining, first_block_to_read, cur_blocks_to_read;
890   uint32_t ndef_bytes_remaining;
891   NFC_HDR* p_cmd_buf;
892   uint8_t *p_cmd_start, *p;
893 
894   p_cmd_buf = rw_t3t_get_cmd_buf();
895   if (p_cmd_buf != nullptr) {
896     /* Construct T3T message */
897     p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
898 
899     /* Calculate number of ndef bytes remaining to read */
900     ndef_bytes_remaining = p_cb->ndef_attrib.ln - p_cb->ndef_rx_offset;
901 
902     /* Calculate number of blocks remaining to read */
903     ndef_blocks_remaining =
904         (uint16_t)((ndef_bytes_remaining + 15) >>
905                    4); /* ndef blocks remaining (rounded upward) */
906 
907     /* Calculate first NDEF block ID */
908     first_block_to_read = (uint16_t)((p_cb->ndef_rx_offset >> 4) + 1);
909 
910     /* Check if remaining blocks can fit into one CHECK command */
911     if (ndef_blocks_remaining <= p_cb->ndef_attrib.nbr) {
912       /* remaining blocks can fit into one CHECK command */
913       cur_blocks_to_read = ndef_blocks_remaining;
914       p_cb->ndef_rx_readlen = ndef_bytes_remaining;
915       p_cb->flags |= RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
916     } else {
917       /* Remaining blocks cannot fit into one CHECK command */
918       cur_blocks_to_read =
919           p_cb->ndef_attrib
920               .nbr; /* Read maximum number of blocks allowed by the peer */
921       p_cb->ndef_rx_readlen = ((uint32_t)p_cb->ndef_attrib.nbr * 16);
922     }
923 
924     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
925         "bytes_remaining: %i, cur_blocks_to_read: %i, is_final: %i",
926         ndef_bytes_remaining, cur_blocks_to_read,
927         (p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT));
928 
929     /* Add CHECK opcode to message  */
930     UINT8_TO_STREAM(p, T3T_MSG_OPC_CHECK_CMD);
931 
932     /* Add IDm to message */
933     ARRAY_TO_STREAM(p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
934 
935     /* Add Service code list */
936     UINT8_TO_STREAM(p, 1); /* Number of services (only 1 service: NDEF) */
937 
938     /* Service code (little-endian format) . If NDEF is read-only, then use
939      * T3T_MSG_NDEF_SC_RO, otherwise use T3T_MSG_NDEF_SC_RW */
940     if (p_cb->ndef_attrib.rwflag == T3T_MSG_NDEF_RWFLAG_RO) {
941       UINT16_TO_STREAM(p, T3T_MSG_NDEF_SC_RO);
942     } else {
943       UINT16_TO_STREAM(p, T3T_MSG_NDEF_SC_RW);
944     }
945 
946     /* Add number of blocks in this CHECK command */
947     UINT8_TO_STREAM(
948         p, cur_blocks_to_read); /* Number of blocks to check in this command */
949 
950     for (block_id = first_block_to_read;
951          block_id < (first_block_to_read + cur_blocks_to_read); block_id++) {
952       if (block_id < 256) {
953         /* Block IDs 0-255 can be specified in '2-byte' format: byte0=0,
954          * byte1=blocknumber */
955         UINT8_TO_STREAM(
956             p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT); /* byte1: len=0;
957                                                             access-mode=0;
958                                                             service code list
959                                                             order=0 */
960         UINT8_TO_STREAM(p, block_id); /* byte1: block number */
961       } else {
962         /* Block IDs 256+ must be specified in '3-byte' format: byte0=80h,
963          * followed by blocknumber */
964         UINT8_TO_STREAM(
965             p,
966             0x00); /* byte0: len=1; access-mode=0; service code list order=0 */
967         UINT16_TO_STREAM(
968             p, block_id); /* byte1-2: block number in little-endian format */
969       }
970     }
971 
972     /* Calculate length of message */
973     p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
974 
975     /* Send the T3T message */
976     retval = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_CHECK_NDEF, p_cmd_buf,
977                              rw_t3t_check_timeout(cur_blocks_to_read));
978   } else {
979     retval = NFC_STATUS_NO_BUFFERS;
980   }
981 
982   return (retval);
983 }
984 
985 /*****************************************************************************
986 **
987 ** Function         rw_t3t_message_set_block_list
988 **
989 ** Description      Add block list to T3T message
990 **
991 ** Returns          Number of bytes added to message
992 **
993 *****************************************************************************/
rw_t3t_message_set_block_list(tRW_T3T_CB * p_cb,uint8_t ** p,uint8_t num_blocks,tT3T_BLOCK_DESC * p_t3t_blocks)994 void rw_t3t_message_set_block_list(tRW_T3T_CB* p_cb, uint8_t** p,
995                                    uint8_t num_blocks,
996                                    tT3T_BLOCK_DESC* p_t3t_blocks) {
997   uint16_t i, cur_service_code;
998   uint8_t service_code_idx, num_services = 0;
999   uint8_t* p_msg_num_services;
1000   uint16_t service_list[T3T_MSG_SERVICE_LIST_MAX];
1001 
1002   /* Add CHECK or UPDATE opcode to message  */
1003   UINT8_TO_STREAM(
1004       (*p), ((p_cb->cur_cmd == RW_T3T_CMD_CHECK) ? T3T_MSG_OPC_CHECK_CMD
1005                                                  : T3T_MSG_OPC_UPDATE_CMD));
1006 
1007   /* Add IDm to message */
1008   ARRAY_TO_STREAM((*p), p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1009 
1010   /* Skip over Number of Services field */
1011   p_msg_num_services = (*p); /* pointer to Number of Services offset */
1012   (*p)++;
1013 
1014   /* Count number of different services are specified in the list, and add
1015    * services to Service Code list */
1016   for (i = 0; i < num_blocks; i++) {
1017     cur_service_code = p_t3t_blocks[i].service_code;
1018 
1019     /* Check if current service_code is already in the service_list */
1020     for (service_code_idx = 0; service_code_idx < num_services;
1021          service_code_idx++) {
1022       if (service_list[service_code_idx] == cur_service_code) break;
1023     }
1024 
1025     if (service_code_idx == num_services) {
1026       /* Service not in the list yet. Add it. */
1027       service_list[service_code_idx] = cur_service_code;
1028       num_services++;
1029 
1030       /* Add service code to T3T message */
1031       UINT16_TO_STREAM((*p), cur_service_code);
1032 
1033       /* Validate num_services */
1034       if (num_services >= T3T_MSG_SERVICE_LIST_MAX) {
1035         LOG(ERROR) << StringPrintf(
1036             "RW T3T: num_services (%i) reaches maximum (%i)", num_services,
1037             T3T_MSG_SERVICE_LIST_MAX);
1038         break;
1039       }
1040     }
1041   }
1042 
1043   /* Add 'Number of Sservices' to the message */
1044   *p_msg_num_services = num_services;
1045 
1046   /* Add 'number of blocks' to the message */
1047   UINT8_TO_STREAM((*p), num_blocks);
1048 
1049   /* Add block descriptors */
1050   for (i = 0; i < num_blocks; i++) {
1051     cur_service_code = p_t3t_blocks[i].service_code;
1052 
1053     /* Check if current service_code is already in the service_list */
1054     for (service_code_idx = 0; service_code_idx < num_services;
1055          service_code_idx++) {
1056       if (service_list[service_code_idx] == cur_service_code) break;
1057     }
1058 
1059     /* Add decriptor to T3T message */
1060     if (p_t3t_blocks[i].block_number > 0xFF) {
1061       UINT8_TO_STREAM((*p), service_code_idx);
1062       UINT16_TO_STREAM((*p), p_t3t_blocks[i].block_number);
1063     } else {
1064       service_code_idx |= T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT;
1065       UINT8_TO_STREAM((*p), service_code_idx);
1066       UINT8_TO_STREAM((*p), p_t3t_blocks[i].block_number);
1067     }
1068   }
1069 }
1070 
1071 /*****************************************************************************
1072 **
1073 ** Function         rw_t3t_send_check_cmd
1074 **
1075 ** Description      Send CHECK command
1076 **
1077 ** Returns          tNFC_STATUS
1078 **
1079 *****************************************************************************/
rw_t3t_send_check_cmd(tRW_T3T_CB * p_cb,uint8_t num_blocks,tT3T_BLOCK_DESC * p_t3t_blocks)1080 tNFC_STATUS rw_t3t_send_check_cmd(tRW_T3T_CB* p_cb, uint8_t num_blocks,
1081                                   tT3T_BLOCK_DESC* p_t3t_blocks) {
1082   NFC_HDR* p_cmd_buf;
1083   uint8_t *p, *p_cmd_start;
1084   tNFC_STATUS retval = NFC_STATUS_OK;
1085 
1086   p_cb->cur_cmd = RW_T3T_CMD_CHECK;
1087   p_cmd_buf = rw_t3t_get_cmd_buf();
1088   if (p_cmd_buf != nullptr) {
1089     /* Construct T3T message */
1090     p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
1091     rw_t3t_message_set_block_list(p_cb, &p, num_blocks, p_t3t_blocks);
1092 
1093     /* Calculate length of message */
1094     p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
1095 
1096     /* Send the T3T message */
1097     retval = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_CHECK, p_cmd_buf,
1098                              rw_t3t_check_timeout(num_blocks));
1099   } else {
1100     retval = NFC_STATUS_NO_BUFFERS;
1101   }
1102 
1103   return (retval);
1104 }
1105 
1106 /*****************************************************************************
1107 **
1108 ** Function         rw_t3t_send_update_cmd
1109 **
1110 ** Description      Send UPDATE command
1111 **
1112 ** Returns          tNFC_STATUS
1113 **
1114 *****************************************************************************/
rw_t3t_send_update_cmd(tRW_T3T_CB * p_cb,uint8_t num_blocks,tT3T_BLOCK_DESC * p_t3t_blocks,uint8_t * p_data)1115 tNFC_STATUS rw_t3t_send_update_cmd(tRW_T3T_CB* p_cb, uint8_t num_blocks,
1116                                    tT3T_BLOCK_DESC* p_t3t_blocks,
1117                                    uint8_t* p_data) {
1118   NFC_HDR* p_cmd_buf;
1119   uint8_t *p, *p_cmd_start;
1120   tNFC_STATUS retval = NFC_STATUS_OK;
1121 
1122   p_cb->cur_cmd = RW_T3T_CMD_UPDATE;
1123   p_cmd_buf = rw_t3t_get_cmd_buf();
1124   if (p_cmd_buf != nullptr) {
1125     /* Construct T3T message */
1126     p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
1127     rw_t3t_message_set_block_list(p_cb, &p, num_blocks, p_t3t_blocks);
1128 
1129     /* Add data blocks to the message */
1130     ARRAY_TO_STREAM(p, p_data, num_blocks * 16);
1131 
1132     /* Calculate length of message */
1133     p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
1134 
1135     /* Send the T3T message */
1136     retval = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_UPDATE, p_cmd_buf,
1137                              rw_t3t_update_timeout(num_blocks));
1138   } else {
1139     retval = NFC_STATUS_NO_BUFFERS;
1140   }
1141 
1142   return (retval);
1143 }
1144 
1145 /*****************************************************************************
1146 **
1147 ** Function         rw_t3t_check_mc_block
1148 **
1149 ** Description      Send command to check Memory Configuration Block
1150 **
1151 ** Returns          tNFC_STATUS
1152 **
1153 *****************************************************************************/
rw_t3t_check_mc_block(tRW_T3T_CB * p_cb)1154 tNFC_STATUS rw_t3t_check_mc_block(tRW_T3T_CB* p_cb) {
1155   NFC_HDR* p_cmd_buf;
1156   uint8_t *p, *p_cmd_start;
1157 
1158   /* Read Memory Configuration block */
1159   p_cmd_buf = rw_t3t_get_cmd_buf();
1160   if (p_cmd_buf != nullptr) {
1161     /* Construct T3T message */
1162     p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
1163 
1164     /* Add CHECK opcode to message  */
1165     UINT8_TO_STREAM(p, T3T_MSG_OPC_CHECK_CMD);
1166 
1167     /* Add IDm to message */
1168     ARRAY_TO_STREAM(p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1169 
1170     /* Add Service code list */
1171     UINT8_TO_STREAM(p, 1); /* Number of services (only 1 service: NDEF) */
1172     UINT16_TO_STREAM(
1173         p, T3T_MSG_NDEF_SC_RO); /* Service code (little-endian format) */
1174 
1175     /* Number of blocks */
1176     UINT8_TO_STREAM(p, 1); /* Number of blocks (only 1 block: Memory
1177                               Configuration Information ) */
1178 
1179     /* Block List element: the Memory Configuration block (block 0x88) */
1180     UINT8_TO_STREAM(p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
1181     UINT8_TO_STREAM(p, T3T_MSG_FELICALITE_BLOCK_ID_MC);
1182 
1183     /* Calculate length of message */
1184     p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
1185 
1186     /* Send the T3T message */
1187     return rw_t3t_send_cmd(p_cb, p_cb->cur_cmd, p_cmd_buf,
1188                            rw_t3t_check_timeout(1));
1189   } else {
1190     LOG(ERROR) << StringPrintf("Unable to allocate buffer to read MC block");
1191     return (NFC_STATUS_NO_BUFFERS);
1192   }
1193 }
1194 
1195 /*****************************************************************************
1196 **
1197 ** Function         rw_t3t_send_raw_frame
1198 **
1199 ** Description      Send raw frame
1200 **
1201 ** Returns          tNFC_STATUS
1202 **
1203 *****************************************************************************/
rw_t3t_send_raw_frame(tRW_T3T_CB * p_cb,uint16_t len,uint8_t * p_data)1204 tNFC_STATUS rw_t3t_send_raw_frame(tRW_T3T_CB* p_cb, uint16_t len,
1205                                   uint8_t* p_data) {
1206   NFC_HDR* p_cmd_buf;
1207   uint8_t* p;
1208   tNFC_STATUS retval = NFC_STATUS_OK;
1209 
1210   /* GKI_BUF2 is used for NFC_RW_POOL */
1211   if (len > GKI_BUF2_SIZE - NCI_MSG_OFFSET_SIZE - NCI_DATA_HDR_SIZE - 2) {
1212     android_errorWriteLog(0x534e4554, "157649467");
1213     return NFC_STATUS_NO_BUFFERS;
1214   }
1215 
1216   p_cmd_buf = rw_t3t_get_cmd_buf();
1217   if (p_cmd_buf != nullptr) {
1218     /* Construct T3T message */
1219     p = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
1220 
1221     /* Add data blocks to the message */
1222     ARRAY_TO_STREAM(p, p_data, len);
1223 
1224     /* Calculate length of message */
1225     p_cmd_buf->len = len;
1226 
1227     /* Send the T3T message */
1228     retval = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_SEND_RAW_FRAME, p_cmd_buf,
1229                              RW_T3T_RAW_FRAME_CMD_TIMEOUT_TICKS);
1230   } else {
1231     retval = NFC_STATUS_NO_BUFFERS;
1232   }
1233 
1234   return (retval);
1235 }
1236 
1237 /*****************************************************************************
1238 **  TAG RESPONSE HANDLERS
1239 *****************************************************************************/
1240 
1241 /*****************************************************************************
1242 **
1243 ** Function         rw_t3t_act_handle_ndef_detect_rsp
1244 **
1245 ** Description      Handle response to NDEF detection
1246 **
1247 ** Returns          Nothing
1248 **
1249 *****************************************************************************/
rw_t3t_act_handle_ndef_detect_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)1250 void rw_t3t_act_handle_ndef_detect_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
1251   uint8_t* p;
1252   uint32_t temp;
1253   uint8_t i;
1254   uint16_t checksum_calc, checksum_rx;
1255   tRW_DETECT_NDEF_DATA evt_data = tRW_DETECT_NDEF_DATA();
1256   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
1257 
1258   evt_data.status = NFC_STATUS_FAILED;
1259   evt_data.flags = RW_NDEF_FL_UNKNOWN;
1260 
1261   /* Check if response code is CHECK resp (for reading NDEF attribute block) */
1262   if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP) {
1263     LOG(ERROR) << StringPrintf(
1264         "Response error: expecting rsp_code %02X, but got %02X",
1265         T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1266     evt_data.status = NFC_STATUS_FAILED;
1267   }
1268   /* Validate status code and NFCID2 response from tag */
1269   else if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
1270             T3T_MSG_RSP_STATUS_OK) /* verify response status code */
1271            || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
1272                       NCI_NFCID2_LEN) != 0)) /* verify response IDm */
1273   {
1274     evt_data.status = NFC_STATUS_FAILED;
1275   } else if (p_msg_rsp->len <
1276              (T3T_MSG_RSP_OFFSET_CHECK_DATA + T3T_MSG_BLOCKSIZE)) {
1277     evt_data.status = NFC_STATUS_FAILED;
1278     android_errorWriteLog(0x534e4554, "120428041");
1279   } else {
1280     /* Get checksum from received ndef attribute msg */
1281     p = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA + T3T_MSG_NDEF_ATTR_INFO_SIZE];
1282     BE_STREAM_TO_UINT16(checksum_rx, p);
1283 
1284     /* Calculate checksum - move check for checsum to beginning */
1285     checksum_calc = 0;
1286     p = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA];
1287     for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) {
1288       checksum_calc += p[i];
1289     }
1290 
1291     /* Validate checksum */
1292     if (checksum_calc != checksum_rx) {
1293       p_cb->ndef_attrib.status =
1294           NFC_STATUS_FAILED; /* only ok or failed passed to the app. can be
1295                                 boolean*/
1296 
1297       LOG(ERROR) << StringPrintf("RW_T3tDetectNDEF checksum failed");
1298     } else {
1299       p_cb->ndef_attrib.status = NFC_STATUS_OK;
1300 
1301       /* Validate version number */
1302       STREAM_TO_UINT8(p_cb->ndef_attrib.version, p);
1303 
1304       if (T3T_GET_MAJOR_VERSION(T3T_MSG_NDEF_VERSION) <
1305           T3T_GET_MAJOR_VERSION(p_cb->ndef_attrib.version)) {
1306         /* Remote tag's MajorVer is newer than our's. Reject NDEF as per T3TOP
1307          * RQ_T3T_NDA_024 */
1308         LOG(ERROR) << StringPrintf(
1309             "RW_T3tDetectNDEF: incompatible NDEF version. Local=0x%02x, "
1310             "Remote=0x%02x",
1311             T3T_MSG_NDEF_VERSION, p_cb->ndef_attrib.version);
1312         p_cb->ndef_attrib.status = NFC_STATUS_FAILED;
1313         evt_data.status = NFC_STATUS_BAD_RESP;
1314       } else {
1315         /* Remote tag's MajorVer is equal or older than our's. NDEF is
1316          * compatible with our version. */
1317 
1318         /* Update NDEF info */
1319         STREAM_TO_UINT8(
1320             p_cb->ndef_attrib.nbr,
1321             p); /* NBr: number of blocks that can be read using one Check
1322                    command */
1323         STREAM_TO_UINT8(p_cb->ndef_attrib.nbw,
1324                         p); /* Nbw: number of blocks that can be written using
1325                                one Update command */
1326         BE_STREAM_TO_UINT16(
1327             p_cb->ndef_attrib.nmaxb,
1328             p); /* Nmaxb: maximum number of blocks available for NDEF data */
1329         BE_STREAM_TO_UINT32(temp, p);
1330         STREAM_TO_UINT8(p_cb->ndef_attrib.writef,
1331                         p); /* WriteFlag: 00h if writing data finished; 0Fh if
1332                                writing data in progress */
1333         STREAM_TO_UINT8(
1334             p_cb->ndef_attrib.rwflag,
1335             p); /* RWFlag: 00h NDEF is read-only; 01h if read/write available */
1336 
1337         /* Get length (3-byte, big-endian) */
1338         STREAM_TO_UINT8(temp, p);                     /* Ln: high-byte */
1339         BE_STREAM_TO_UINT16(p_cb->ndef_attrib.ln, p); /* Ln: lo-word */
1340         p_cb->ndef_attrib.ln += (temp << 16);
1341 
1342         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1343             "Detected NDEF Ver: 0x%02x", p_cb->ndef_attrib.version);
1344         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1345             "Detected NDEF Attributes: Nbr=%i, Nbw=%i, Nmaxb=%i, WriteF=%i, "
1346             "RWFlag=%i, Ln=%i",
1347             p_cb->ndef_attrib.nbr, p_cb->ndef_attrib.nbw,
1348             p_cb->ndef_attrib.nmaxb, p_cb->ndef_attrib.writef,
1349             p_cb->ndef_attrib.rwflag, p_cb->ndef_attrib.ln);
1350         if (p_cb->ndef_attrib.nbr > T3T_MSG_NUM_BLOCKS_CHECK_MAX ||
1351             p_cb->ndef_attrib.nbw > T3T_MSG_NUM_BLOCKS_UPDATE_MAX) {
1352           /* It would result in CHECK Responses exceeding the maximum length
1353            * of an NFC-F Frame */
1354           LOG(ERROR) << StringPrintf(
1355               "Unsupported NDEF Attributes value: Nbr=%i, Nbw=%i, Nmaxb=%i,"
1356               "WriteF=%i, RWFlag=%i, Ln=%i",
1357               p_cb->ndef_attrib.nbr, p_cb->ndef_attrib.nbw,
1358               p_cb->ndef_attrib.nmaxb, p_cb->ndef_attrib.writef,
1359               p_cb->ndef_attrib.rwflag, p_cb->ndef_attrib.ln);
1360           p_cb->ndef_attrib.status = NFC_STATUS_FAILED;
1361           evt_data.status = NFC_STATUS_BAD_RESP;
1362         } else {
1363           /* Set data for RW_T3T_NDEF_DETECT_EVT */
1364           evt_data.status = p_cb->ndef_attrib.status;
1365           evt_data.cur_size = p_cb->ndef_attrib.ln;
1366           evt_data.max_size = (uint32_t)p_cb->ndef_attrib.nmaxb * 16;
1367           evt_data.protocol = NFC_PROTOCOL_T3T;
1368           evt_data.flags = (RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED);
1369           if (p_cb->ndef_attrib.rwflag == T3T_MSG_NDEF_RWFLAG_RO)
1370             evt_data.flags |= RW_NDEF_FL_READ_ONLY;
1371         }
1372       }
1373     }
1374   }
1375 
1376   DLOG_IF(INFO, nfc_debug_enabled)
1377       << StringPrintf("RW_T3tDetectNDEF response: %i", evt_data.status);
1378 
1379   p_cb->rw_state = RW_T3T_STATE_IDLE;
1380   rw_t3t_update_ndef_flag(&evt_data.flags);
1381   /* Notify app of NDEF detection result */
1382   tRW_DATA rw_data;
1383   rw_data.ndef = evt_data;
1384   (*(rw_cb.p_cback))(RW_T3T_NDEF_DETECT_EVT, &rw_data);
1385 
1386   GKI_freebuf(p_msg_rsp);
1387 }
1388 
1389 /*****************************************************************************
1390 **
1391 ** Function         rw_t3t_act_handle_check_rsp
1392 **
1393 ** Description      Handle response to CHECK command
1394 **
1395 ** Returns          Nothing
1396 **
1397 *****************************************************************************/
rw_t3t_act_handle_check_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)1398 void rw_t3t_act_handle_check_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
1399   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
1400   tRW_READ_DATA evt_data;
1401   tNFC_STATUS nfc_status = NFC_STATUS_OK;
1402 
1403   /* Validate response from tag */
1404   if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
1405        T3T_MSG_RSP_STATUS_OK) /* verify response status code */
1406       || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
1407                  NCI_NFCID2_LEN) != 0)) /* verify response IDm */
1408   {
1409     nfc_status = NFC_STATUS_FAILED;
1410     GKI_freebuf(p_msg_rsp);
1411   } else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP) {
1412     LOG(ERROR) << StringPrintf(
1413         "Response error: expecting rsp_code %02X, but got %02X",
1414         T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1415     nfc_status = NFC_STATUS_FAILED;
1416     GKI_freebuf(p_msg_rsp);
1417   } else if (p_msg_rsp->len >= T3T_MSG_RSP_OFFSET_CHECK_DATA) {
1418     /* Copy incoming data into buffer */
1419     p_msg_rsp->offset +=
1420         T3T_MSG_RSP_OFFSET_CHECK_DATA; /* Skip over t3t header */
1421     p_msg_rsp->len -= T3T_MSG_RSP_OFFSET_CHECK_DATA;
1422     evt_data.status = NFC_STATUS_OK;
1423     evt_data.p_data = p_msg_rsp;
1424     tRW_DATA rw_data;
1425     rw_data.data = evt_data;
1426     (*(rw_cb.p_cback))(RW_T3T_CHECK_EVT, &rw_data);
1427   } else {
1428     android_errorWriteLog(0x534e4554, "120503926");
1429     nfc_status = NFC_STATUS_FAILED;
1430     GKI_freebuf(p_msg_rsp);
1431   }
1432 
1433   p_cb->rw_state = RW_T3T_STATE_IDLE;
1434 
1435   tRW_DATA rw_data;
1436   rw_data.status = nfc_status;
1437   (*(rw_cb.p_cback))(RW_T3T_CHECK_CPLT_EVT, &rw_data);
1438 }
1439 
1440 /*****************************************************************************
1441 **
1442 ** Function         rw_t3t_act_handle_update_rsp
1443 **
1444 ** Description      Handle response to UPDATE command
1445 **
1446 ** Returns          Nothing
1447 **
1448 *****************************************************************************/
rw_t3t_act_handle_update_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)1449 void rw_t3t_act_handle_update_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
1450   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
1451   tRW_READ_DATA evt_data = tRW_READ_DATA();
1452 
1453   /* Validate response from tag */
1454   if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
1455        T3T_MSG_RSP_STATUS_OK) /* verify response status code */
1456       || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
1457                  NCI_NFCID2_LEN) != 0)) /* verify response IDm */
1458   {
1459     evt_data.status = NFC_STATUS_FAILED;
1460   } else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP) {
1461     LOG(ERROR) << StringPrintf(
1462         "Response error: expecting rsp_code %02X, but got %02X",
1463         T3T_MSG_OPC_UPDATE_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1464     evt_data.status = NFC_STATUS_FAILED;
1465   } else {
1466     /* Copy incoming data into buffer */
1467     evt_data.status = NFC_STATUS_OK;
1468   }
1469 
1470   p_cb->rw_state = RW_T3T_STATE_IDLE;
1471 
1472   tRW_DATA rw_data;
1473   rw_data.data = evt_data;
1474   (*(rw_cb.p_cback))(RW_T3T_UPDATE_CPLT_EVT, &rw_data);
1475 
1476   GKI_freebuf(p_msg_rsp);
1477 }
1478 
1479 /*****************************************************************************
1480 **
1481 ** Function         rw_t3t_act_handle_raw_senddata_rsp
1482 **
1483 ** Description      Handle response to NDEF detection
1484 **
1485 ** Returns          Nothing
1486 **
1487 *****************************************************************************/
rw_t3t_act_handle_raw_senddata_rsp(tRW_T3T_CB * p_cb,tNFC_DATA_CEVT * p_data)1488 void rw_t3t_act_handle_raw_senddata_rsp(tRW_T3T_CB* p_cb,
1489                                         tNFC_DATA_CEVT* p_data) {
1490   tRW_READ_DATA evt_data;
1491   NFC_HDR* p_pkt = p_data->p_data;
1492 
1493   DLOG_IF(INFO, nfc_debug_enabled)
1494       << StringPrintf("RW T3T Raw Frame: Len [0x%X] Status [%s]", p_pkt->len,
1495                       NFC_GetStatusName(p_data->status).c_str());
1496 
1497   /* Copy incoming data into buffer */
1498   evt_data.status = p_data->status;
1499   evt_data.p_data = p_pkt;
1500 
1501   p_cb->rw_state = RW_T3T_STATE_IDLE;
1502 
1503   tRW_DATA rw_data;
1504   rw_data.data = evt_data;
1505   (*(rw_cb.p_cback))(RW_T3T_RAW_FRAME_EVT, &rw_data);
1506 }
1507 
1508 /*****************************************************************************
1509 **
1510 ** Function         rw_t3t_act_handle_check_ndef_rsp
1511 **
1512 ** Description      Handle response to NDEF read segment
1513 **
1514 ** Returns          Nothing
1515 **
1516 *****************************************************************************/
rw_t3t_act_handle_check_ndef_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)1517 void rw_t3t_act_handle_check_ndef_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
1518   bool check_complete = true;
1519   tNFC_STATUS nfc_status = NFC_STATUS_OK;
1520   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
1521   uint8_t rsp_num_bytes_rx;
1522 
1523   if (p_msg_rsp->len < T3T_MSG_RSP_OFFSET_CHECK_DATA) {
1524     LOG(ERROR) << StringPrintf("%s invalid len", __func__);
1525     nfc_status = NFC_STATUS_FAILED;
1526     GKI_freebuf(p_msg_rsp);
1527     android_errorWriteLog(0x534e4554, "120428637");
1528     /* Validate response from tag */
1529   } else if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
1530               T3T_MSG_RSP_STATUS_OK) /* verify response status code */
1531              || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
1532                         NCI_NFCID2_LEN) != 0) /* verify response IDm */
1533              || (p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] !=
1534                  ((p_cb->ndef_rx_readlen + 15) >>
1535                   4))) /* verify length of response */
1536   {
1537     LOG(ERROR) << StringPrintf(
1538         "Response error: bad status, nfcid2, or invalid len: %i %i",
1539         p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS],
1540         ((p_cb->ndef_rx_readlen + 15) >> 4));
1541     nfc_status = NFC_STATUS_FAILED;
1542     GKI_freebuf(p_msg_rsp);
1543   } else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP) {
1544     LOG(ERROR) << StringPrintf(
1545         "Response error: expecting rsp_code %02X, but got %02X",
1546         T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1547     nfc_status = NFC_STATUS_FAILED;
1548     GKI_freebuf(p_msg_rsp);
1549   } else if (p_msg_rsp->len >= T3T_MSG_RSP_OFFSET_CHECK_DATA &&
1550              p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] > 0) {
1551     /* Notify app of NDEF segment received */
1552     /* Number of bytes received, according to header */
1553     rsp_num_bytes_rx = p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] * 16;
1554     p_cb->ndef_rx_offset += p_cb->ndef_rx_readlen;
1555     p_msg_rsp->offset +=
1556         T3T_MSG_RSP_OFFSET_CHECK_DATA; /* Skip over t3t header (point to block
1557                                           data) */
1558     p_msg_rsp->len -= T3T_MSG_RSP_OFFSET_CHECK_DATA;
1559 
1560     /* Verify that the bytes received is really the amount indicated in the
1561      * check-response header */
1562     if (rsp_num_bytes_rx > p_msg_rsp->len) {
1563       LOG(ERROR) << StringPrintf(
1564           "Response error: CHECK rsp header indicates %i bytes, but only "
1565           "received %i bytes",
1566           rsp_num_bytes_rx, p_msg_rsp->len);
1567       nfc_status = NFC_STATUS_FAILED;
1568       GKI_freebuf(p_msg_rsp);
1569     } else {
1570       /* If this is the the final block, then set len to reflect only valid
1571        * bytes (do not include padding to 16-byte boundary) */
1572       if ((p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT) &&
1573           (p_cb->ndef_attrib.ln & 0x000F)) {
1574         if (rsp_num_bytes_rx < (16 - (p_cb->ndef_attrib.ln & 0x000F))) {
1575           nfc_status = NFC_STATUS_FAILED;
1576           GKI_freebuf(p_msg_rsp);
1577           android_errorWriteLog(0x534e4554, "224002331");
1578           return;
1579         }
1580         rsp_num_bytes_rx -= (16 - (p_cb->ndef_attrib.ln & 0x000F));
1581       }
1582 
1583       p_msg_rsp->len = rsp_num_bytes_rx;
1584       tRW_DATA rw_data;
1585       rw_data.data.status = NFC_STATUS_OK;
1586       rw_data.data.p_data = p_msg_rsp;
1587       (*(rw_cb.p_cback))(RW_T3T_CHECK_EVT, &rw_data);
1588 
1589       /* Send CHECK cmd for next NDEF segment, if needed */
1590       if (!(p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT)) {
1591         nfc_status = rw_t3t_send_next_ndef_check_cmd(p_cb);
1592         if (nfc_status == NFC_STATUS_OK) {
1593           /* Still getting more segments. Don't send RW_T3T_CHECK_CPLT_EVT yet
1594            */
1595           check_complete = false;
1596         }
1597       }
1598     }
1599   } else {
1600     android_errorWriteLog(0x534e4554, "120502559");
1601     GKI_freebuf(p_msg_rsp);
1602     nfc_status = NFC_STATUS_FAILED;
1603     LOG(ERROR) << StringPrintf("Underflow in p_msg_rsp->len!");
1604   }
1605 
1606   /* Notify app of RW_T3T_CHECK_CPLT_EVT if entire NDEF has been read, or if
1607    * failure */
1608   if (check_complete) {
1609     p_cb->rw_state = RW_T3T_STATE_IDLE;
1610     tRW_DATA evt_data;
1611     evt_data.status = nfc_status;
1612     (*(rw_cb.p_cback))(RW_T3T_CHECK_CPLT_EVT, &evt_data);
1613   }
1614 }
1615 
1616 /*****************************************************************************
1617 **
1618 ** Function         rw_t3t_act_handle_update_ndef_rsp
1619 **
1620 ** Description      Handle response to NDEF write segment
1621 **
1622 ** Returns          Nothing
1623 **
1624 *****************************************************************************/
rw_t3t_act_handle_update_ndef_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)1625 void rw_t3t_act_handle_update_ndef_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
1626   bool update_complete = true;
1627   tNFC_STATUS nfc_status = NFC_STATUS_OK;
1628   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
1629 
1630   /* Check nfcid2 and status of response */
1631   if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
1632        T3T_MSG_RSP_STATUS_OK) /* verify response status code */
1633       || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
1634                  NCI_NFCID2_LEN) != 0)) /* verify response IDm */
1635   {
1636     nfc_status = NFC_STATUS_FAILED;
1637   }
1638   /* Validate response opcode */
1639   else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP) {
1640     LOG(ERROR) << StringPrintf(
1641         "Response error: expecting rsp_code %02X, but got %02X",
1642         T3T_MSG_OPC_UPDATE_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1643     nfc_status = NFC_STATUS_FAILED;
1644   }
1645   /* If this is response to final UPDATE, then update NDEF local size */
1646   else if (p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT) {
1647     /* If successful, update current NDEF size */
1648     p_cb->ndef_attrib.ln = p_cb->ndef_msg_len;
1649   }
1650   /*  If any more NDEF bytes to update, then send next UPDATE command */
1651   else if (p_cb->ndef_msg_bytes_sent < p_cb->ndef_msg_len) {
1652     /* Send UPDATE command for next segment of NDEF */
1653     nfc_status = rw_t3t_send_next_ndef_update_cmd(p_cb);
1654     if (nfc_status == NFC_STATUS_OK) {
1655       /* Wait for update response */
1656       update_complete = false;
1657     }
1658   }
1659   /*  Otherwise, no more NDEF bytes. Send final UPDATE for Attribute Information
1660      block */
1661   else {
1662     p_cb->flags |= RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
1663     nfc_status = rw_t3t_send_update_ndef_attribute_cmd(p_cb, false);
1664     if (nfc_status == NFC_STATUS_OK) {
1665       /* Wait for update response */
1666       update_complete = false;
1667     }
1668   }
1669 
1670   /* If update is completed, then notify app */
1671   if (update_complete) {
1672     p_cb->rw_state = RW_T3T_STATE_IDLE;
1673     tRW_DATA evt_data;
1674     evt_data.status = nfc_status;
1675     (*(rw_cb.p_cback))(RW_T3T_UPDATE_CPLT_EVT, &evt_data);
1676   }
1677 
1678   GKI_freebuf(p_msg_rsp);
1679 
1680   return;
1681 }
1682 
1683 /*****************************************************************************
1684 **
1685 ** Function         rw_t3t_handle_get_sc_poll_rsp
1686 **
1687 ** Description      Handle POLL response for getting system codes
1688 **
1689 ** Returns          Nothing
1690 **
1691 *****************************************************************************/
rw_t3t_handle_get_sc_poll_rsp(tRW_T3T_CB * p_cb,uint8_t nci_status,uint8_t num_responses,uint8_t sensf_res_buf_size,uint8_t * p_sensf_res_buf)1692 static void rw_t3t_handle_get_sc_poll_rsp(tRW_T3T_CB* p_cb, uint8_t nci_status,
1693                                           uint8_t num_responses,
1694                                           uint8_t sensf_res_buf_size,
1695                                           uint8_t* p_sensf_res_buf) {
1696   uint8_t* p;
1697   uint16_t sc;
1698 
1699   /* Get the system code from the response */
1700   if ((nci_status == NCI_STATUS_OK) && (num_responses > 0) &&
1701       (sensf_res_buf_size >=
1702        (RW_T3T_SENSF_RES_RD_OFFSET + RW_T3T_SENSF_RES_RD_LEN))) {
1703     p = &p_sensf_res_buf[RW_T3T_SENSF_RES_RD_OFFSET];
1704     BE_STREAM_TO_UINT16(sc, p);
1705 
1706     DLOG_IF(INFO, nfc_debug_enabled)
1707         << StringPrintf("FeliCa detected (RD, system code %04X)", sc);
1708     if (p_cb->num_system_codes < T3T_MAX_SYSTEM_CODES) {
1709       p_cb->system_codes[p_cb->num_system_codes++] = sc;
1710     } else {
1711       LOG(ERROR) << StringPrintf("Exceed T3T_MAX_SYSTEM_CODES!");
1712       android_errorWriteLog(0x534e4554, "120499324");
1713     }
1714   }
1715 
1716   rw_t3t_handle_get_system_codes_cplt();
1717 }
1718 
1719 /*****************************************************************************
1720 **
1721 ** Function         rw_t3t_handle_ndef_detect_poll_rsp
1722 **
1723 ** Description      Handle POLL response for getting system codes
1724 **
1725 ** Returns          Nothing
1726 **
1727 *****************************************************************************/
rw_t3t_handle_ndef_detect_poll_rsp(tRW_T3T_CB * p_cb,uint8_t nci_status,uint8_t num_responses)1728 static void rw_t3t_handle_ndef_detect_poll_rsp(tRW_T3T_CB* p_cb,
1729                                                uint8_t nci_status,
1730                                                uint8_t num_responses) {
1731   NFC_HDR* p_cmd_buf;
1732   uint8_t *p, *p_cmd_start;
1733   tRW_DATA evt_data;
1734 
1735   /* Validate response for NDEF poll */
1736   if ((nci_status == NCI_STATUS_OK) && (num_responses > 0)) {
1737     /* Tag responded for NDEF poll */
1738     p_cb->cur_active_sc = T3T_SYSTEM_CODE_NDEF;
1739 
1740     /* Read NDEF attribute block */
1741     p_cmd_buf = rw_t3t_get_cmd_buf();
1742     if (p_cmd_buf != nullptr) {
1743       /* Construct T3T message */
1744       p = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
1745 
1746       /* Add CHECK opcode to message  */
1747       UINT8_TO_STREAM(p, T3T_MSG_OPC_CHECK_CMD);
1748 
1749       /* Add IDm to message */
1750       ARRAY_TO_STREAM(p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1751 
1752       /* Add Service code list */
1753       UINT8_TO_STREAM(p, 1); /* Number of services (only 1 service: NDEF) */
1754       UINT16_TO_STREAM(
1755           p, T3T_MSG_NDEF_SC_RO); /* Service code (little-endian format) */
1756 
1757       /* Number of blocks */
1758       UINT8_TO_STREAM(
1759           p,
1760           1); /* Number of blocks (only 1 block: NDEF Attribute Information ) */
1761 
1762       /* Block List element: the NDEF attribute information block (block 0) */
1763       UINT8_TO_STREAM(p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
1764       UINT8_TO_STREAM(p, 0);
1765 
1766       /* Calculate length of message */
1767       p_cmd_buf->len = (uint16_t)(p - p_cmd_start);
1768 
1769       /* Send the T3T message */
1770       evt_data.status = rw_t3t_send_cmd(p_cb, RW_T3T_CMD_DETECT_NDEF, p_cmd_buf,
1771                                         rw_t3t_check_timeout(1));
1772       if (evt_data.status == NFC_STATUS_OK) {
1773         /* CHECK command sent. Wait for response */
1774         return;
1775       }
1776     }
1777     nci_status = NFC_STATUS_FAILED;
1778   }
1779 
1780   /* NDEF detection failed */
1781   p_cb->rw_state = RW_T3T_STATE_IDLE;
1782   evt_data.ndef.status = nci_status;
1783   evt_data.ndef.flags = RW_NDEF_FL_UNKNOWN;
1784   rw_t3t_update_ndef_flag(&evt_data.ndef.flags);
1785   (*(rw_cb.p_cback))(RW_T3T_NDEF_DETECT_EVT, &evt_data);
1786 }
1787 
1788 /*****************************************************************************
1789 **
1790 ** Function         rw_t3t_update_block
1791 **
1792 ** Description      Send UPDATE command for single block
1793 **                  (for formatting/configuring read only)
1794 **
1795 ** Returns          tNFC_STATUS
1796 **
1797 *****************************************************************************/
rw_t3t_update_block(tRW_T3T_CB * p_cb,uint8_t block_id,uint8_t * p_block_data)1798 tNFC_STATUS rw_t3t_update_block(tRW_T3T_CB* p_cb, uint8_t block_id,
1799                                 uint8_t* p_block_data) {
1800   uint8_t *p_dst, *p_cmd_start;
1801   NFC_HDR* p_cmd_buf;
1802   tNFC_STATUS status;
1803 
1804   p_cmd_buf = rw_t3t_get_cmd_buf();
1805   if (p_cmd_buf != nullptr) {
1806     p_dst = p_cmd_start = (uint8_t*)(p_cmd_buf + 1) + p_cmd_buf->offset;
1807 
1808     /* Add UPDATE opcode to message  */
1809     UINT8_TO_STREAM(p_dst, T3T_MSG_OPC_UPDATE_CMD);
1810 
1811     /* Add IDm to message */
1812     ARRAY_TO_STREAM(p_dst, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1813 
1814     /* Add Service code list */
1815     UINT8_TO_STREAM(p_dst, 1); /* Number of services (only 1 service: NDEF) */
1816     UINT16_TO_STREAM(
1817         p_dst, T3T_MSG_NDEF_SC_RW); /* Service code (little-endian format) */
1818 
1819     /* Number of blocks */
1820     UINT8_TO_STREAM(p_dst, 1);
1821 
1822     /* Add Block list element for MC */
1823     UINT8_TO_STREAM(p_dst, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
1824     UINT8_TO_STREAM(p_dst, block_id);
1825 
1826     /* Copy MC data to UPDATE message */
1827     ARRAY_TO_STREAM(p_dst, p_block_data, T3T_MSG_BLOCKSIZE);
1828 
1829     /* Calculate length of message */
1830     p_cmd_buf->len = (uint16_t)(p_dst - p_cmd_start);
1831 
1832     /* Send the T3T message */
1833     status = rw_t3t_send_cmd(p_cb, p_cb->cur_cmd, p_cmd_buf,
1834                              rw_t3t_update_timeout(1));
1835   } else {
1836     /* Unable to send UPDATE command */
1837     status = NFC_STATUS_NO_BUFFERS;
1838   }
1839 
1840   return (status);
1841 }
1842 
1843 /*****************************************************************************
1844 **
1845 ** Function         rw_t3t_handle_fmt_poll_rsp
1846 **
1847 ** Description      Handle POLL response for formatting felica-lite
1848 **
1849 ** Returns          Nothing
1850 **
1851 *****************************************************************************/
rw_t3t_handle_fmt_poll_rsp(tRW_T3T_CB * p_cb,uint8_t nci_status,uint8_t num_responses)1852 static void rw_t3t_handle_fmt_poll_rsp(tRW_T3T_CB* p_cb, uint8_t nci_status,
1853                                        uint8_t num_responses) {
1854   tRW_DATA evt_data;
1855 
1856   evt_data.status = NFC_STATUS_OK;
1857 
1858   /* Validate response for poll response */
1859   if ((nci_status == NCI_STATUS_OK) && (num_responses > 0)) {
1860     /* Tag responded for Felica-Lite poll */
1861     p_cb->cur_active_sc = T3T_SYSTEM_CODE_FELICA_LITE;
1862     /* Get MemoryControl block */
1863     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1864         "Felica-Lite tag detected...getting Memory Control block.");
1865 
1866     p_cb->rw_substate = RW_T3T_FMT_SST_CHECK_MC_BLK;
1867 
1868     /* Send command to check Memory Configuration block */
1869     evt_data.status = rw_t3t_check_mc_block(p_cb);
1870   } else {
1871     LOG(ERROR) << StringPrintf("Felica-Lite tag not detected");
1872     evt_data.status = NFC_STATUS_FAILED;
1873   }
1874 
1875   /* If error, notify upper layer */
1876   if (evt_data.status != NFC_STATUS_OK) {
1877     rw_t3t_format_cplt(evt_data.status);
1878   }
1879 }
1880 
1881 /*****************************************************************************
1882 **
1883 ** Function         rw_t3t_act_handle_fmt_rsp
1884 **
1885 ** Description      Handle response for formatting codes
1886 **
1887 ** Returns          Nothing
1888 **
1889 *****************************************************************************/
rw_t3t_act_handle_fmt_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)1890 void rw_t3t_act_handle_fmt_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
1891   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
1892   uint8_t* p_mc;
1893   tRW_DATA evt_data;
1894 
1895   evt_data.status = NFC_STATUS_OK;
1896 
1897   /* Check tags's response for reading MemoryControl block */
1898   if (p_cb->rw_substate == RW_T3T_FMT_SST_CHECK_MC_BLK) {
1899     /* Validate response opcode */
1900     if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP) {
1901       LOG(ERROR) << StringPrintf(
1902           "Response error: expecting rsp_code %02X, but got %02X",
1903           T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1904       evt_data.status = NFC_STATUS_FAILED;
1905     }
1906     /* Validate status code and NFCID2 response from tag */
1907     else if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
1908               T3T_MSG_RSP_STATUS_OK) /* verify response status code */
1909              || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
1910                         NCI_NFCID2_LEN) != 0)) /* verify response IDm */
1911     {
1912       evt_data.status = NFC_STATUS_FAILED;
1913     } else if (p_msg_rsp->len <
1914                (T3T_MSG_RSP_OFFSET_CHECK_DATA + T3T_MSG_BLOCKSIZE)) {
1915       evt_data.status = NFC_STATUS_FAILED;
1916       android_errorWriteLog(0x534e4554, "120506143");
1917     } else {
1918       /* Check if memory configuration (MC) block to see if SYS_OP=1 (NDEF
1919        * enabled) */
1920       p_mc = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA]; /* Point to MC data of
1921                                                            CHECK response */
1922 
1923       if (p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] != 0x01) {
1924         /* Tag is not currently enabled for NDEF. Indicate that we need to
1925          * update the MC block */
1926 
1927         /* Set SYS_OP field to 0x01 (enable NDEF) */
1928         p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] = 0x01;
1929 
1930         /* Set RF_PRM field to 0x07 (procedure of issuance) */
1931         p_mc[T3T_MSG_FELICALITE_MC_OFFSET_RF_PRM] = 0x07;
1932 
1933         /* Construct and send UPDATE message to write MC block */
1934         p_cb->rw_substate = RW_T3T_FMT_SST_UPDATE_MC_BLK;
1935         evt_data.status =
1936             rw_t3t_update_block(p_cb, T3T_MSG_FELICALITE_BLOCK_ID_MC, p_mc);
1937       } else {
1938         /* SYS_OP=1: ndef already enabled. Just need to update attribute
1939          * information block */
1940         p_cb->rw_substate = RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB;
1941         evt_data.status =
1942             rw_t3t_update_block(p_cb, 0, (uint8_t*)rw_t3t_default_attrib_info);
1943       }
1944     }
1945 
1946     /* If error, notify upper layer */
1947     if (evt_data.status != NFC_STATUS_OK) {
1948       rw_t3t_format_cplt(evt_data.status);
1949     }
1950   } else if (p_cb->rw_substate == RW_T3T_FMT_SST_UPDATE_MC_BLK) {
1951     /* Validate response opcode */
1952     if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP) ||
1953         (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK))
1954 
1955     {
1956       LOG(ERROR) << StringPrintf("Response error: rsp_code=%02X, status=%02X",
1957                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE],
1958                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1]);
1959       evt_data.status = NFC_STATUS_FAILED;
1960     } else {
1961       /* SYS_OP=1: ndef already enabled. Just need to update attribute
1962        * information block */
1963       p_cb->rw_substate = RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB;
1964       evt_data.status =
1965           rw_t3t_update_block(p_cb, 0, (uint8_t*)rw_t3t_default_attrib_info);
1966     }
1967 
1968     /* If error, notify upper layer */
1969     if (evt_data.status != NFC_STATUS_OK) {
1970       rw_t3t_format_cplt(evt_data.status);
1971     }
1972   } else if (p_cb->rw_substate == RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB) {
1973     /* Validate response opcode */
1974     if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP) ||
1975         (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK))
1976 
1977     {
1978       LOG(ERROR) << StringPrintf("Response error: rsp_code=%02X, status=%02X",
1979                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE],
1980                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1]);
1981       evt_data.status = NFC_STATUS_FAILED;
1982     }
1983 
1984     rw_t3t_format_cplt(evt_data.status);
1985   }
1986 
1987   GKI_freebuf(p_msg_rsp);
1988 }
1989 
1990 /*****************************************************************************
1991 **
1992 ** Function         rw_t3t_handle_sro_poll_rsp
1993 **
1994 ** Description      Handle POLL response for configuring felica-lite read only
1995 **
1996 ** Returns          Nothing
1997 **
1998 *****************************************************************************/
rw_t3t_handle_sro_poll_rsp(tRW_T3T_CB * p_cb,uint8_t nci_status,uint8_t num_responses)1999 static void rw_t3t_handle_sro_poll_rsp(tRW_T3T_CB* p_cb, uint8_t nci_status,
2000                                        uint8_t num_responses) {
2001   tRW_DATA evt_data;
2002   uint8_t rw_t3t_ndef_attrib_info[T3T_MSG_BLOCKSIZE];
2003   uint8_t* p;
2004   uint8_t tempU8;
2005   uint16_t checksum, i;
2006   uint32_t tempU32 = 0;
2007 
2008   evt_data.status = NFC_STATUS_OK;
2009 
2010   /* Validate response for poll response */
2011   if ((nci_status == NCI_STATUS_OK) && (num_responses > 0)) {
2012     /* Tag responded for Felica-Lite poll */
2013     if (p_cb->ndef_attrib.rwflag != T3T_MSG_NDEF_RWFLAG_RO) {
2014       /* First update attribute information block */
2015       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2016           "Felica-Lite tag detected...update NDef attribution block.");
2017 
2018       p_cb->rw_substate = RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB;
2019 
2020       p = rw_t3t_ndef_attrib_info;
2021 
2022       UINT8_TO_STREAM(p, p_cb->ndef_attrib.version);
2023 
2024       /* Update NDEF info */
2025       UINT8_TO_STREAM(
2026           p, p_cb->ndef_attrib.nbr); /* NBr: number of blocks that can be read
2027                                         using one Check command */
2028       UINT8_TO_STREAM(p, p_cb->ndef_attrib.nbw); /* Nbw: number of blocks that
2029                                                     can be written using one
2030                                                     Update command */
2031       UINT16_TO_BE_STREAM(
2032           p, p_cb->ndef_attrib.nmaxb); /* Nmaxb: maximum number of blocks
2033                                           available for NDEF data */
2034       UINT32_TO_BE_STREAM(p, tempU32);
2035       UINT8_TO_STREAM(p,
2036                       p_cb->ndef_attrib.writef); /* WriteFlag: 00h if writing
2037                                                     data finished; 0Fh if
2038                                                     writing data in progress */
2039       UINT8_TO_STREAM(p, 0x00); /* RWFlag: 00h NDEF is read-only */
2040 
2041       tempU8 = (uint8_t)(p_cb->ndef_attrib.ln >> 16);
2042       /* Get length (3-byte, big-endian) */
2043       UINT8_TO_STREAM(p, tempU8);                   /* Ln: high-byte */
2044       UINT16_TO_BE_STREAM(p, p_cb->ndef_attrib.ln); /* Ln: lo-word */
2045 
2046       /* Calculate and append Checksum */
2047       checksum = 0;
2048       for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) {
2049         checksum += rw_t3t_ndef_attrib_info[i];
2050       }
2051       UINT16_TO_BE_STREAM(p, checksum);
2052 
2053       evt_data.status =
2054           rw_t3t_update_block(p_cb, 0, (uint8_t*)rw_t3t_ndef_attrib_info);
2055     } else if (p_cb->cur_cmd == RW_T3T_CMD_SET_READ_ONLY_HARD) {
2056       /* NDEF is already read only, Read and update MemoryControl block */
2057       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2058           "Felica-Lite tag detected...getting Memory Control block.");
2059       p_cb->rw_substate = RW_T3T_SRO_SST_CHECK_MC_BLK;
2060 
2061       /* Send command to check Memory Configuration block */
2062       evt_data.status = rw_t3t_check_mc_block(p_cb);
2063     }
2064   } else {
2065     LOG(ERROR) << StringPrintf("Felica-Lite tag not detected");
2066     evt_data.status = NFC_STATUS_FAILED;
2067   }
2068 
2069   /* If error, notify upper layer */
2070   if (evt_data.status != NFC_STATUS_OK) {
2071     rw_t3t_set_readonly_cplt(evt_data.status);
2072   }
2073 }
2074 
2075 /*****************************************************************************
2076 **
2077 ** Function         rw_t3t_act_handle_sro_rsp
2078 **
2079 ** Description      Handle response for setting read only codes
2080 **
2081 ** Returns          Nothing
2082 **
2083 *****************************************************************************/
rw_t3t_act_handle_sro_rsp(tRW_T3T_CB * p_cb,NFC_HDR * p_msg_rsp)2084 void rw_t3t_act_handle_sro_rsp(tRW_T3T_CB* p_cb, NFC_HDR* p_msg_rsp) {
2085   uint8_t* p_t3t_rsp = (uint8_t*)(p_msg_rsp + 1) + p_msg_rsp->offset;
2086   uint8_t* p_mc;
2087   tRW_DATA evt_data;
2088 
2089   evt_data.status = NFC_STATUS_OK;
2090 
2091   if (p_cb->rw_substate == RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB) {
2092     /* Validate response opcode */
2093     if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP) ||
2094         (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK))
2095 
2096     {
2097       LOG(ERROR) << StringPrintf("Response error: rsp_code=%02X, status=%02X",
2098                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE],
2099                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1]);
2100       evt_data.status = NFC_STATUS_FAILED;
2101     } else {
2102       p_cb->ndef_attrib.rwflag = T3T_MSG_NDEF_RWFLAG_RO;
2103       if (p_cb->cur_cmd == RW_T3T_CMD_SET_READ_ONLY_HARD) {
2104         p_cb->rw_substate = RW_T3T_SRO_SST_CHECK_MC_BLK;
2105 
2106         /* Send command to check Memory Configuration block */
2107         evt_data.status = rw_t3t_check_mc_block(p_cb);
2108       } else {
2109         rw_t3t_set_readonly_cplt(evt_data.status);
2110       }
2111     }
2112   } else if (p_cb->rw_substate == RW_T3T_SRO_SST_CHECK_MC_BLK) {
2113     /* Check tags's response for reading MemoryControl block, Validate response
2114      * opcode */
2115     if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP) {
2116       LOG(ERROR) << StringPrintf(
2117           "Response error: expecting rsp_code %02X, but got %02X",
2118           T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
2119       evt_data.status = NFC_STATUS_FAILED;
2120     }
2121     /* Validate status code and NFCID2 response from tag */
2122     else if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] !=
2123               T3T_MSG_RSP_STATUS_OK) /* verify response status code */
2124              || (memcmp(p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
2125                         NCI_NFCID2_LEN) != 0)) /* verify response IDm */
2126     {
2127       evt_data.status = NFC_STATUS_FAILED;
2128     } else if (p_msg_rsp->len <
2129                (T3T_MSG_RSP_OFFSET_CHECK_DATA + T3T_MSG_BLOCKSIZE)) {
2130       evt_data.status = NFC_STATUS_FAILED;
2131       android_errorWriteLog(0x534e4554, "120506143");
2132     } else {
2133       /* Check if memory configuration (MC) block to see if SYS_OP=1 (NDEF
2134        * enabled) */
2135       p_mc = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA]; /* Point to MC data of
2136                                                            CHECK response */
2137 
2138       evt_data.status = NFC_STATUS_FAILED;
2139       if (p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] == 0x01) {
2140         /* Set MC_SP field with MC[0] = 0x00 & MC[1] = 0xC0 (Hardlock) to change
2141          * access permission from RW to RO */
2142         p_mc[T3T_MSG_FELICALITE_MC_OFFSET_MC_SP] = 0x00;
2143         /* Not changing the access permission of Subtraction Register and
2144          * MC[0:1] */
2145         p_mc[T3T_MSG_FELICALITE_MC_OFFSET_MC_SP + 1] = 0xC0;
2146 
2147         /* Set RF_PRM field to 0x07 (procedure of issuance) */
2148         p_mc[T3T_MSG_FELICALITE_MC_OFFSET_RF_PRM] = 0x07;
2149 
2150         /* Construct and send UPDATE message to write MC block */
2151         p_cb->rw_substate = RW_T3T_SRO_SST_UPDATE_MC_BLK;
2152         evt_data.status =
2153             rw_t3t_update_block(p_cb, T3T_MSG_FELICALITE_BLOCK_ID_MC, p_mc);
2154       }
2155     }
2156   } else if (p_cb->rw_substate == RW_T3T_SRO_SST_UPDATE_MC_BLK) {
2157     /* Validate response opcode */
2158     if ((p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP) ||
2159         (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK))
2160 
2161     {
2162       LOG(ERROR) << StringPrintf("Response error: rsp_code=%02X, status=%02X",
2163                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE],
2164                                  p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1]);
2165       evt_data.status = NFC_STATUS_FAILED;
2166     } else {
2167       rw_t3t_set_readonly_cplt(evt_data.status);
2168     }
2169   }
2170 
2171   /* If error, notify upper layer */
2172   if (evt_data.status != NFC_STATUS_OK) {
2173     rw_t3t_set_readonly_cplt(evt_data.status);
2174   }
2175 
2176   GKI_freebuf(p_msg_rsp);
2177 }
2178 
2179 /*******************************************************************************
2180 **
2181 ** Function         rw_t3t_data_cback
2182 **
2183 ** Description      This callback function receives the data from NFCC.
2184 **
2185 ** Returns          none
2186 **
2187 *******************************************************************************/
rw_t3t_data_cback(uint8_t conn_id,tNFC_DATA_CEVT * p_data)2188 void rw_t3t_data_cback(__attribute__((unused)) uint8_t conn_id,
2189                        tNFC_DATA_CEVT* p_data) {
2190   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2191   NFC_HDR* p_msg = p_data->p_data;
2192   bool free_msg = false; /* if TRUE, free msg buffer before returning */
2193   uint8_t *p, sod;
2194 
2195   /* Stop rsponse timer */
2196   nfc_stop_quick_timer(&p_cb->timer);
2197 
2198 #if (RW_STATS_INCLUDED == TRUE)
2199   /* Update rx stats */
2200   rw_main_update_rx_stats(p_msg->len);
2201 #endif /* RW_STATS_INCLUDED */
2202 
2203   /* Check if we are expecting a response */
2204   if (p_cb->rw_state != RW_T3T_STATE_COMMAND_PENDING) {
2205     /*
2206     **  This must be raw frame response
2207     **  send raw frame to app with SoD
2208     */
2209     rw_t3t_act_handle_raw_senddata_rsp(p_cb, p_data);
2210   }
2211   /* Sanity check: verify msg len is big enough to contain t3t header */
2212   else if (p_msg->len < T3T_MSG_RSP_COMMON_HDR_LEN) {
2213     LOG(ERROR) << StringPrintf(
2214         "T3T: invalid Type3 Tag Message (invalid len: %i)", p_msg->len);
2215     free_msg = true;
2216     rw_t3t_process_frame_error();
2217   } else {
2218     /* Check for RF frame error */
2219     p = (uint8_t*)(p_msg + 1) + p_msg->offset;
2220     sod = p[0];
2221 
2222     if (p_msg->len < sod || p[sod] != NCI_STATUS_OK) {
2223       LOG(ERROR) << "T3T: rf frame error";
2224       GKI_freebuf(p_msg);
2225       rw_t3t_process_frame_error();
2226       return;
2227     }
2228 
2229     /* Skip over SoD */
2230     p_msg->offset++;
2231     p_msg->len--;
2232 
2233     /* Get response code */
2234     switch (p_cb->cur_cmd) {
2235       case RW_T3T_CMD_DETECT_NDEF:
2236         rw_t3t_act_handle_ndef_detect_rsp(p_cb, p_msg);
2237         break;
2238 
2239       case RW_T3T_CMD_CHECK_NDEF:
2240         rw_t3t_act_handle_check_ndef_rsp(p_cb, p_msg);
2241         break;
2242 
2243       case RW_T3T_CMD_UPDATE_NDEF:
2244         rw_t3t_act_handle_update_ndef_rsp(p_cb, p_msg);
2245         break;
2246 
2247       case RW_T3T_CMD_CHECK:
2248         rw_t3t_act_handle_check_rsp(p_cb, p_msg);
2249         break;
2250 
2251       case RW_T3T_CMD_UPDATE:
2252         rw_t3t_act_handle_update_rsp(p_cb, p_msg);
2253         break;
2254 
2255       case RW_T3T_CMD_SEND_RAW_FRAME:
2256         rw_t3t_act_handle_raw_senddata_rsp(p_cb, p_data);
2257         break;
2258 
2259       case RW_T3T_CMD_FORMAT:
2260         rw_t3t_act_handle_fmt_rsp(p_cb, p_msg);
2261         break;
2262 
2263       case RW_T3T_CMD_SET_READ_ONLY_SOFT:
2264       case RW_T3T_CMD_SET_READ_ONLY_HARD:
2265         rw_t3t_act_handle_sro_rsp(p_cb, p_msg);
2266         break;
2267 
2268       default:
2269         GKI_freebuf(p_msg);
2270         break;
2271     }
2272   }
2273 
2274   if (free_msg) {
2275     GKI_freebuf(p_msg);
2276   }
2277 }
2278 
2279 /*******************************************************************************
2280 **
2281 ** Function         rw_t3t_conn_cback
2282 **
2283 ** Description      This callback function receives the events/data from NFCC.
2284 **
2285 ** Returns          none
2286 **
2287 *******************************************************************************/
rw_t3t_conn_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)2288 void rw_t3t_conn_cback(uint8_t conn_id, tNFC_CONN_EVT event,
2289                        tNFC_CONN* p_data) {
2290   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2291   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2292       "rw_t3t_conn_cback: conn_id=%i, evt=0x%02x", conn_id, event);
2293 
2294   /* Only handle NFC_RF_CONN_ID conn_id */
2295   if (conn_id != NFC_RF_CONN_ID) {
2296     return;
2297   }
2298 
2299   switch (event) {
2300     case NFC_DEACTIVATE_CEVT:
2301       rw_t3t_unselect();
2302       break;
2303 
2304     case NFC_DATA_CEVT: /* check for status in tNFC_CONN */
2305       if ((p_data != nullptr) && ((p_data->data.status == NFC_STATUS_OK) ||
2306                                (p_data->data.status == NFC_STATUS_CONTINUE))) {
2307         rw_t3t_data_cback(conn_id, &(p_data->data));
2308         break;
2309       } else if (p_data && p_data->data.p_data != nullptr) {
2310         /* Free the response buffer in case of error response */
2311         GKI_freebuf((NFC_HDR*)(p_data->data.p_data));
2312         p_data->data.p_data = nullptr;
2313       }
2314       /* Data event with error status...fall through to NFC_ERROR_CEVT case */
2315       FALLTHROUGH_INTENDED;
2316 
2317     case NFC_ERROR_CEVT:
2318       nfc_stop_quick_timer(&p_cb->timer);
2319 
2320 #if (RW_STATS_INCLUDED == TRUE)
2321       rw_main_update_trans_error_stats();
2322 #endif /* RW_STATS_INCLUDED */
2323 
2324       if (event == NFC_ERROR_CEVT)
2325         rw_t3t_process_error(NFC_STATUS_TIMEOUT);
2326       else if (p_data)
2327         rw_t3t_process_error(p_data->status);
2328       break;
2329 
2330     default:
2331       break;
2332   }
2333 }
2334 
2335 /*******************************************************************************
2336 **
2337 ** Function         rw_t3t_mrti_to_a_b
2338 **
2339 ** Description      Converts the given MRTI (Maximum Response Time Information)
2340 **                  to the base to calculate timeout value.
2341 **                  (The timeout value is a + b * number_blocks)
2342 **
2343 ** Returns          NFC_STATUS_OK
2344 **
2345 *******************************************************************************/
rw_t3t_mrti_to_a_b(uint8_t mrti,uint32_t * p_a,uint32_t * p_b)2346 static void rw_t3t_mrti_to_a_b(uint8_t mrti, uint32_t* p_a, uint32_t* p_b) {
2347   uint8_t a, b, e;
2348 
2349   a = (mrti & 0x7) + 1; /* A is bit 0 ~ bit 2 */
2350   mrti >>= 3;
2351   b = (mrti & 0x7) + 1; /* B is bit 3 ~ bit 5 */
2352   mrti >>= 3;
2353   e = mrti & 0x3;                 /* E is bit 6 ~ bit 7 */
2354   *p_a = rw_t3t_mrti_base[e] * a; /* (A+1) * base (i.e T/t3t * 4^E) */
2355   *p_b = rw_t3t_mrti_base[e] * b; /* (B+1) * base (i.e T/t3t * 4^E) */
2356 }
2357 
2358 /*******************************************************************************
2359 **
2360 ** Function         rw_t3t_select
2361 **
2362 ** Description      Called by NFC manager when a Type3 tag has been activated
2363 **
2364 ** Returns          NFC_STATUS_OK
2365 **
2366 *******************************************************************************/
rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],uint8_t mrti_check,uint8_t mrti_update)2367 tNFC_STATUS rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],
2368                           uint8_t mrti_check, uint8_t mrti_update) {
2369   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2370 
2371   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2372 
2373   memcpy(p_cb->peer_nfcid2, peer_nfcid2,
2374          NCI_NFCID2_LEN); /* Store tag's NFCID2 */
2375   p_cb->ndef_attrib.status =
2376       NFC_STATUS_NOT_INITIALIZED; /* Indicate that NDEF detection has not been
2377                                      performed yet */
2378   p_cb->rw_state = RW_T3T_STATE_IDLE;
2379   p_cb->flags = 0;
2380   rw_t3t_mrti_to_a_b(mrti_check, &p_cb->check_tout_a, &p_cb->check_tout_b);
2381   rw_t3t_mrti_to_a_b(mrti_update, &p_cb->update_tout_a, &p_cb->update_tout_b);
2382 
2383   /* Alloc cmd buf for retransmissions */
2384   if (p_cb->p_cur_cmd_buf == nullptr) {
2385     p_cb->p_cur_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
2386     if (p_cb->p_cur_cmd_buf == nullptr) {
2387       LOG(ERROR) << StringPrintf(
2388           "rw_t3t_select: unable to allocate buffer for retransmission");
2389       p_cb->rw_state = RW_T3T_STATE_NOT_ACTIVATED;
2390       return (NFC_STATUS_FAILED);
2391     }
2392   }
2393 
2394   NFC_SetStaticRfCback(rw_t3t_conn_cback);
2395 
2396   return NFC_STATUS_OK;
2397 }
2398 
2399 /*******************************************************************************
2400 **
2401 ** Function         rw_t3t_unselect
2402 **
2403 ** Description      Called by NFC manager when a Type3 tag has been de-activated
2404 **
2405 ** Returns          NFC_STATUS_OK
2406 **
2407 *******************************************************************************/
rw_t3t_unselect()2408 static tNFC_STATUS rw_t3t_unselect() {
2409   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2410 
2411 #if (RW_STATS_INCLUDED == TRUE)
2412   /* Display stats */
2413   rw_main_log_stats();
2414 #endif /* RW_STATS_INCLUDED */
2415 
2416   /* Stop t3t timer (if started) */
2417   nfc_stop_quick_timer(&p_cb->timer);
2418 
2419   /* Free cmd buf for retransmissions */
2420   if (p_cb->p_cur_cmd_buf) {
2421     GKI_freebuf(p_cb->p_cur_cmd_buf);
2422     p_cb->p_cur_cmd_buf = nullptr;
2423   }
2424 
2425   p_cb->rw_state = RW_T3T_STATE_NOT_ACTIVATED;
2426   NFC_SetStaticRfCback(nullptr);
2427 
2428   return NFC_STATUS_OK;
2429 }
2430 
2431 /*******************************************************************************
2432 **
2433 ** Function         rw_t3t_update_ndef_flag
2434 **
2435 ** Description      set additional NDEF Flags for felica lite tag
2436 **
2437 ** Returns          updated NDEF Flag value
2438 **
2439 *******************************************************************************/
rw_t3t_update_ndef_flag(uint8_t * p_flag)2440 static void rw_t3t_update_ndef_flag(uint8_t* p_flag) {
2441   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2442   uint8_t xx;
2443 
2444   for (xx = 0; xx < p_cb->num_system_codes; xx++) {
2445     if (p_cb->system_codes[xx] == T3T_SYSTEM_CODE_FELICA_LITE) {
2446       *p_flag &= ~RW_NDEF_FL_UNKNOWN;
2447       *p_flag |= (RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATABLE);
2448       break;
2449     }
2450   }
2451 }
2452 
2453 /*******************************************************************************
2454 **
2455 ** Function         rw_t3t_cmd_str
2456 **
2457 ** Description      Converts cmd_id to command string for logging
2458 **
2459 ** Returns          command string
2460 **
2461 *******************************************************************************/
rw_t3t_cmd_str(uint8_t cmd_id)2462 static std::string rw_t3t_cmd_str(uint8_t cmd_id) {
2463   switch (cmd_id) {
2464     case RW_T3T_CMD_DETECT_NDEF:
2465       return "RW_T3T_CMD_DETECT_NDEF";
2466     case RW_T3T_CMD_CHECK_NDEF:
2467       return "RW_T3T_CMD_CHECK_NDEF";
2468     case RW_T3T_CMD_UPDATE_NDEF:
2469       return "RW_T3T_CMD_UPDATE_NDEF";
2470     case RW_T3T_CMD_CHECK:
2471       return "RW_T3T_CMD_CHECK";
2472     case RW_T3T_CMD_UPDATE:
2473       return "RW_T3T_CMD_UPDATE";
2474     case RW_T3T_CMD_SEND_RAW_FRAME:
2475       return "RW_T3T_CMD_SEND_RAW_FRAME";
2476     case RW_T3T_CMD_GET_SYSTEM_CODES:
2477       return "RW_T3T_CMD_GET_SYSTEM_CODES";
2478     default:
2479       return "Unknown";
2480   }
2481 }
2482 
2483 /*******************************************************************************
2484 **
2485 ** Function         rw_t3t_state_str
2486 **
2487 ** Description      Converts state_id to command string for logging
2488 **
2489 ** Returns          command string
2490 **
2491 *******************************************************************************/
rw_t3t_state_str(uint8_t state_id)2492 static std::string rw_t3t_state_str(uint8_t state_id) {
2493   switch (state_id) {
2494     case RW_T3T_STATE_NOT_ACTIVATED:
2495       return "RW_T3T_STATE_NOT_ACTIVATED";
2496     case RW_T3T_STATE_IDLE:
2497       return "RW_T3T_STATE_IDLE";
2498     case RW_T3T_STATE_COMMAND_PENDING:
2499       return "RW_T3T_STATE_COMMAND_PENDING";
2500     default:
2501       return "Unknown";
2502   }
2503 }
2504 
2505 /*****************************************************************************
2506 **  Type3 Tag API Functions
2507 *****************************************************************************/
2508 
2509 /*****************************************************************************
2510 **
2511 ** Function         RW_T3tDetectNDef
2512 **
2513 ** Description
2514 **      This function is used to perform NDEF detection on a Type 3 tag, and
2515 **      retrieve the tag's NDEF attribute information (block 0).
2516 **
2517 **      Before using this API, the application must call RW_SelectTagType to
2518 **      indicate that a Type 3 tag has been activated, and to provide the
2519 **      tag's Manufacture ID (IDm) .
2520 **
2521 ** Returns
2522 **      NFC_STATUS_OK: ndef detection procedure started
2523 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2524 **      NFC_STATUS_FAILED: other error
2525 **
2526 *****************************************************************************/
RW_T3tDetectNDef(void)2527 tNFC_STATUS RW_T3tDetectNDef(void) {
2528   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2529   tNFC_STATUS retval = NFC_STATUS_OK;
2530 
2531   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2532 
2533   /* Check if we are in valid state to handle this API */
2534   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2535     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2536                                p_cb->rw_state);
2537     return (NFC_STATUS_FAILED);
2538   }
2539 
2540   retval = (tNFC_STATUS)nci_snd_t3t_polling(T3T_SYSTEM_CODE_NDEF, 0, 0);
2541   if (retval == NCI_STATUS_OK) {
2542     p_cb->cur_cmd = RW_T3T_CMD_DETECT_NDEF;
2543     p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
2544     p_cb->cur_poll_rc = 0;
2545     p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2546     p_cb->flags |= RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP;
2547 
2548     /* start timer for waiting for responses */
2549     rw_t3t_start_poll_timer(p_cb);
2550   }
2551 
2552   return (retval);
2553 }
2554 
2555 /*****************************************************************************
2556 **
2557 ** Function         RW_T3tCheckNDef
2558 **
2559 ** Description
2560 **      Retrieve NDEF contents from a Type3 tag.
2561 **
2562 **      The RW_T3T_CHECK_EVT event is used to notify the application for each
2563 **      segment of NDEF data received. The RW_T3T_CHECK_CPLT_EVT event is used
2564 **      to notify the application all segments have been received.
2565 **
2566 **      Before using this API, the RW_T3tDetectNDef function must be called to
2567 **      verify that the tag contains NDEF data, and to retrieve the NDEF
2568 **      attributes.
2569 **
2570 **      Internally, this command will be separated into multiple Tag 3 Check
2571 **      commands (if necessary) - depending on the tag's Nbr (max number of
2572 **      blocks per read) attribute.
2573 **
2574 ** Returns
2575 **      NFC_STATUS_OK: check command started
2576 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2577 **      NFC_STATUS_FAILED: other error
2578 **
2579 *****************************************************************************/
RW_T3tCheckNDef(void)2580 tNFC_STATUS RW_T3tCheckNDef(void) {
2581   tNFC_STATUS retval = NFC_STATUS_OK;
2582   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2583 
2584   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2585 
2586   /* Check if we are in valid state to handle this API */
2587   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2588     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2589                                p_cb->rw_state);
2590     return (NFC_STATUS_FAILED);
2591   } else if (p_cb->ndef_attrib.status !=
2592              NFC_STATUS_OK) /* NDEF detection not performed yet? */
2593   {
2594     LOG(ERROR) << StringPrintf("Error: NDEF detection not performed yet");
2595     return (NFC_STATUS_NOT_INITIALIZED);
2596   } else if (p_cb->ndef_attrib.ln == 0) {
2597     LOG(ERROR) << StringPrintf("Type 3 tag contains empty NDEF message");
2598     return (NFC_STATUS_FAILED);
2599   } else if (p_cb->ndef_attrib.writef ==
2600              T3T_MSG_NDEF_WRITEF_ON) /* Tag's NDEF memory write in progress? */
2601   {
2602     LOG(ERROR) << StringPrintf(
2603         "%s - WriteFlag ON: NDEF data may be inconsistent, "
2604         "conclude NDEF Read procedure",
2605         __func__);
2606     return (NFC_STATUS_FAILED);
2607   }
2608 
2609   /* Check number of blocks needed for this update */
2610   p_cb->flags &= ~RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
2611   p_cb->ndef_rx_offset = 0;
2612   retval = rw_t3t_send_next_ndef_check_cmd(p_cb);
2613 
2614   return (retval);
2615 }
2616 
2617 /*****************************************************************************
2618 **
2619 ** Function         RW_T3tUpdateNDef
2620 **
2621 ** Description
2622 **      Write NDEF contents to a Type3 tag.
2623 **
2624 **      The RW_T3T_UPDATE_CPLT_EVT callback event will be used to notify the
2625 **      application of the response.
2626 **
2627 **      Before using this API, the RW_T3tDetectNDef function must be called to
2628 **      verify that the tag contains NDEF data, and to retrieve the NDEF
2629 **      attributes.
2630 **
2631 **      Internally, this command will be separated into multiple Tag 3 Update
2632 **      commands (if necessary) - depending on the tag's Nbw (max number of
2633 **      blocks per write) attribute.
2634 **
2635 ** Returns
2636 **      NFC_STATUS_OK: check command started
2637 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2638 **      NFC_STATUS_REFUSED: tag is read-only
2639 **      NFC_STATUS_BUFFER_FULL: len exceeds tag's maximum size
2640 **      NFC_STATUS_FAILED: other error
2641 **
2642 *****************************************************************************/
RW_T3tUpdateNDef(uint32_t len,uint8_t * p_data)2643 tNFC_STATUS RW_T3tUpdateNDef(uint32_t len, uint8_t* p_data) {
2644   tNFC_STATUS retval = NFC_STATUS_OK;
2645   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2646 
2647   DLOG_IF(INFO, nfc_debug_enabled)
2648       << StringPrintf("RW_T3tUpdateNDef (len=%i)", len);
2649 
2650   /* Check if we are in valid state to handle this API */
2651   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2652     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2653                                p_cb->rw_state);
2654     return (NFC_STATUS_FAILED);
2655   } else if (p_cb->ndef_attrib.status !=
2656              NFC_STATUS_OK) /* NDEF detection not performed yet? */
2657   {
2658     LOG(ERROR) << StringPrintf("Error: NDEF detection not performed yet");
2659     return (NFC_STATUS_NOT_INITIALIZED);
2660   } else if (len > (((uint32_t)p_cb->ndef_attrib.nmaxb) *
2661                     16)) /* Len exceed's tag's NDEF memory? */
2662   {
2663     return (NFC_STATUS_BUFFER_FULL);
2664   } else if (p_cb->ndef_attrib.rwflag ==
2665              T3T_MSG_NDEF_RWFLAG_RO) /* Tag's NDEF memory is read-only? */
2666   {
2667     return (NFC_STATUS_REFUSED);
2668   }
2669 
2670   /* Check number of blocks needed for this update */
2671   p_cb->flags &= ~RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
2672   p_cb->ndef_msg_bytes_sent = 0;
2673   p_cb->ndef_msg_len = len;
2674   p_cb->ndef_msg = p_data;
2675 
2676   /* Send initial UPDATE command for NDEF Attribute Info */
2677   retval = rw_t3t_send_update_ndef_attribute_cmd(p_cb, true);
2678 
2679   return (retval);
2680 }
2681 
2682 /*****************************************************************************
2683 **
2684 ** Function         RW_T3tCheck
2685 **
2686 ** Description
2687 **      Read (non-NDEF) contents from a Type3 tag.
2688 **
2689 **      The RW_READ_EVT event is used to notify the application for each
2690 **      segment of NDEF data received. The RW_READ_CPLT_EVT event is used to
2691 **      notify the application all segments have been received.
2692 **
2693 **      Before using this API, the application must call RW_SelectTagType to
2694 **      indicate that a Type 3 tag has been activated, and to provide the
2695 **      tag's Manufacture ID (IDm) .
2696 **
2697 ** Returns
2698 **      NFC_STATUS_OK: check command started
2699 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2700 **      NFC_STATUS_FAILED: other error
2701 **
2702 *****************************************************************************/
RW_T3tCheck(uint8_t num_blocks,tT3T_BLOCK_DESC * t3t_blocks)2703 tNFC_STATUS RW_T3tCheck(uint8_t num_blocks, tT3T_BLOCK_DESC* t3t_blocks) {
2704   tNFC_STATUS retval = NFC_STATUS_OK;
2705   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2706 
2707   DLOG_IF(INFO, nfc_debug_enabled)
2708       << StringPrintf("RW_T3tCheck (num_blocks = %i)", num_blocks);
2709 
2710   /* Check if we are in valid state to handle this API */
2711   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2712     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2713                                p_cb->rw_state);
2714     return (NFC_STATUS_FAILED);
2715   }
2716 
2717   /* Send the CHECK command */
2718   retval = rw_t3t_send_check_cmd(p_cb, num_blocks, t3t_blocks);
2719 
2720   return (retval);
2721 }
2722 
2723 /*****************************************************************************
2724 **
2725 ** Function         RW_T3tUpdate
2726 **
2727 ** Description
2728 **      Write (non-NDEF) contents to a Type3 tag.
2729 **
2730 **      The RW_WRITE_CPLT_EVT event is used to notify the application all
2731 **      segments have been received.
2732 **
2733 **      Before using this API, the application must call RW_SelectTagType to
2734 **      indicate that a Type 3 tag has been activated, and to provide the tag's
2735 **      Manufacture ID (IDm) .
2736 **
2737 ** Returns
2738 **      NFC_STATUS_OK: check command started
2739 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2740 **      NFC_STATUS_FAILED: other error
2741 **
2742 *****************************************************************************/
RW_T3tUpdate(uint8_t num_blocks,tT3T_BLOCK_DESC * t3t_blocks,uint8_t * p_data)2743 tNFC_STATUS RW_T3tUpdate(uint8_t num_blocks, tT3T_BLOCK_DESC* t3t_blocks,
2744                          uint8_t* p_data) {
2745   tNFC_STATUS retval = NFC_STATUS_OK;
2746   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2747 
2748   DLOG_IF(INFO, nfc_debug_enabled)
2749       << StringPrintf("RW_T3tUpdate (num_blocks = %i)", num_blocks);
2750 
2751   /* Check if we are in valid state to handle this API */
2752   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2753     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2754                                p_cb->rw_state);
2755     return (NFC_STATUS_FAILED);
2756   }
2757 
2758   /* Send the UPDATE command */
2759   retval = rw_t3t_send_update_cmd(p_cb, num_blocks, t3t_blocks, p_data);
2760 
2761   return (retval);
2762 }
2763 
2764 /*****************************************************************************
2765 **
2766 ** Function         RW_T3tPresenceCheck
2767 **
2768 ** Description
2769 **      Check if the tag is still in the field.
2770 **
2771 **      The RW_T3T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
2772 **      or non-presence.
2773 **
2774 ** Returns
2775 **      NFC_STATUS_OK, if raw data frame sent
2776 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2777 **      NFC_STATUS_FAILED: other error
2778 **
2779 *****************************************************************************/
RW_T3tPresenceCheck(void)2780 tNFC_STATUS RW_T3tPresenceCheck(void) {
2781   tNFC_STATUS retval = NFC_STATUS_OK;
2782   tRW_DATA evt_data;
2783   tRW_CB* p_rw_cb = &rw_cb;
2784 
2785   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2786 
2787   /* If RW_SelectTagType was not called (no conn_callback) return failure */
2788   if (!(p_rw_cb->p_cback)) {
2789     retval = NFC_STATUS_FAILED;
2790   }
2791   /* If we are not activated, then RW_T3T_PRESENCE_CHECK_EVT status=FAIL */
2792   else if (p_rw_cb->tcb.t3t.rw_state == RW_T3T_STATE_NOT_ACTIVATED) {
2793     evt_data.status = NFC_STATUS_FAILED;
2794     (*p_rw_cb->p_cback)(RW_T3T_PRESENCE_CHECK_EVT, &evt_data);
2795   }
2796   /* If command is pending */
2797   else if (p_rw_cb->tcb.t3t.rw_state == RW_T3T_STATE_COMMAND_PENDING) {
2798     /* If already performing presence check, return error */
2799     if (p_rw_cb->tcb.t3t.flags & RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP) {
2800       DLOG_IF(INFO, nfc_debug_enabled)
2801           << StringPrintf("RW_T3tPresenceCheck already in progress");
2802       retval = NFC_STATUS_FAILED;
2803     }
2804     /* If busy with any other command, assume that the tag is present */
2805     else {
2806       evt_data.status = NFC_STATUS_OK;
2807       (*p_rw_cb->p_cback)(RW_T3T_PRESENCE_CHECK_EVT, &evt_data);
2808     }
2809   } else {
2810     /* IDLE state: send POLL command */
2811     retval = (tNFC_STATUS)nci_snd_t3t_polling(0xFFFF, T3T_POLL_RC_SC, 0x03);
2812     if (retval == NCI_STATUS_OK) {
2813       p_rw_cb->tcb.t3t.flags |= RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
2814       p_rw_cb->tcb.t3t.rw_state = RW_T3T_STATE_COMMAND_PENDING;
2815       p_rw_cb->tcb.t3t.cur_poll_rc = 0;
2816 
2817       /* start timer for waiting for responses */
2818       rw_t3t_start_poll_timer(&p_rw_cb->tcb.t3t);
2819     } else {
2820       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
2821           "RW_T3tPresenceCheck error sending NCI_RF_T3T_POLLING cmd (status = "
2822           "0x%0x)",
2823           retval);
2824     }
2825   }
2826 
2827   return (retval);
2828 }
2829 
2830 /*****************************************************************************
2831 **
2832 ** Function         RW_T3tPoll
2833 **
2834 ** Description
2835 **      Send POLL command
2836 **
2837 ** Returns
2838 **      NFC_STATUS_OK, if raw data frame sent
2839 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2840 **      NFC_STATUS_FAILED: other error
2841 **
2842 *****************************************************************************/
RW_T3tPoll(uint16_t system_code,tT3T_POLL_RC rc,uint8_t tsn)2843 tNFC_STATUS RW_T3tPoll(uint16_t system_code, tT3T_POLL_RC rc, uint8_t tsn) {
2844   tNFC_STATUS retval = NFC_STATUS_OK;
2845   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2846 
2847   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2848 
2849   /* Check if we are in valid state to handle this API */
2850   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2851     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2852                                p_cb->rw_state);
2853     return (NFC_STATUS_FAILED);
2854   }
2855 
2856   retval = (tNFC_STATUS)nci_snd_t3t_polling(system_code, (uint8_t)rc, tsn);
2857   if (retval == NCI_STATUS_OK) {
2858     /* start timer for waiting for responses */
2859     p_cb->cur_poll_rc = rc;
2860     p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2861     p_cb->flags |= RW_T3T_FL_W4_USER_POLL_RSP;
2862     rw_t3t_start_poll_timer(p_cb);
2863   }
2864 
2865   return (retval);
2866 }
2867 
2868 /*****************************************************************************
2869 **
2870 ** Function         RW_T3tSendRawFrame
2871 **
2872 ** Description
2873 **      This function is called to send a raw data frame to the peer device.
2874 **      When type 3 tag receives response from peer, the callback function
2875 **      will be called with a RW_T3T_RAW_FRAME_EVT [Table 6].
2876 **
2877 **      Before using this API, the application must call RW_SelectTagType to
2878 **      indicate that a Type 3 tag has been activated.
2879 **
2880 **      The raw frame should be a properly formatted Type 3 tag message.
2881 **
2882 ** Returns
2883 **      NFC_STATUS_OK, if raw data frame sent
2884 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2885 **      NFC_STATUS_FAILED: other error
2886 **
2887 *****************************************************************************/
RW_T3tSendRawFrame(uint16_t len,uint8_t * p_data)2888 tNFC_STATUS RW_T3tSendRawFrame(uint16_t len, uint8_t* p_data) {
2889   tNFC_STATUS retval = NFC_STATUS_OK;
2890   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2891 
2892   DLOG_IF(INFO, nfc_debug_enabled)
2893       << StringPrintf("RW_T3tSendRawFrame (len = %i)", len);
2894 
2895   /* Check if we are in valid state to handle this API */
2896   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2897     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2898                                p_cb->rw_state);
2899     return (NFC_STATUS_FAILED);
2900   }
2901 
2902   /* Send the UPDATE command */
2903   retval = rw_t3t_send_raw_frame(p_cb, len, p_data);
2904 
2905   return (retval);
2906 }
2907 
2908 /*****************************************************************************
2909 **
2910 ** Function         RW_T3tGetSystemCodes
2911 **
2912 ** Description
2913 **      Get systems codes supported by the activated tag:
2914 **              Poll for wildcard (FFFF, RC=1):
2915 **
2916 **      Before using this API, the application must call RW_SelectTagType to
2917 **      indicate that a Type 3 tag has been activated.
2918 **
2919 ** Returns
2920 **      NFC_STATUS_OK, if raw data frame sent
2921 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2922 **      NFC_STATUS_FAILED: other error
2923 **
2924 *****************************************************************************/
RW_T3tGetSystemCodes(void)2925 tNFC_STATUS RW_T3tGetSystemCodes(void) {
2926   tNFC_STATUS retval = NFC_STATUS_OK;
2927   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2928 
2929   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2930 
2931   /* Check if we are in valid state to handle this API */
2932   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2933     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2934                                p_cb->rw_state);
2935     return (NFC_STATUS_FAILED);
2936   } else {
2937     /* Until the card answers properly to SC=12FCh, by default, consider
2938        the card as a Felica card not NDEF compatible, answering to SC=0x88B4
2939        possibly */
2940     p_cb->cur_active_sc = T3T_SYSTEM_CODE_FELICA_LITE;
2941 
2942     retval = (tNFC_STATUS)nci_snd_t3t_polling(0xFFFF, T3T_POLL_RC_SC, 0x0F);
2943     if (retval == NCI_STATUS_OK) {
2944       p_cb->cur_cmd = RW_T3T_CMD_GET_SYSTEM_CODES;
2945       p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
2946       p_cb->cur_poll_rc = T3T_POLL_RC_SC;
2947       p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2948       p_cb->flags |= RW_T3T_FL_W4_GET_SC_POLL_RSP;
2949       p_cb->num_system_codes = 0;
2950 
2951       /* start timer for waiting for responses */
2952       rw_t3t_start_poll_timer(p_cb);
2953     }
2954   }
2955 
2956   return (retval);
2957 }
2958 
2959 /*****************************************************************************
2960 **
2961 ** Function         RW_T3tFormatNDef
2962 **
2963 ** Description
2964 **      Format a type-3 tag for NDEF.
2965 **
2966 **      Only Felica-Lite tags are supported by this API. The
2967 **      RW_T3T_FORMAT_CPLT_EVT is used to notify the status of the operation.
2968 **
2969 ** Returns
2970 **      NFC_STATUS_OK: ndef detection procedure started
2971 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2972 **      NFC_STATUS_FAILED: other error
2973 **
2974 *****************************************************************************/
RW_T3tFormatNDef(void)2975 tNFC_STATUS RW_T3tFormatNDef(void) {
2976   tNFC_STATUS retval = NFC_STATUS_OK;
2977   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
2978 
2979   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
2980 
2981   /* Check if we are in valid state to handle this API */
2982   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
2983     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
2984                                p_cb->rw_state);
2985     return (NFC_STATUS_FAILED);
2986   } else {
2987     /* Poll tag, to see if Felica-Lite system is supported */
2988     retval = (tNFC_STATUS)nci_snd_t3t_polling(T3T_SYSTEM_CODE_FELICA_LITE,
2989                                               T3T_POLL_RC_SC, 0);
2990     if (retval == NCI_STATUS_OK) {
2991       p_cb->cur_cmd = RW_T3T_CMD_FORMAT;
2992       p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
2993       p_cb->cur_poll_rc = T3T_POLL_RC_SC;
2994       p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2995       p_cb->rw_substate = RW_T3T_FMT_SST_POLL_FELICA_LITE;
2996       p_cb->flags |= RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP;
2997 
2998       /* start timer for waiting for responses */
2999       rw_t3t_start_poll_timer(p_cb);
3000     }
3001   }
3002 
3003   return (retval);
3004 }
3005 
3006 /*****************************************************************************
3007 **
3008 ** Function         RW_T3tSetReadOnly
3009 **
3010 ** Description      This function performs NDEF read-only procedure
3011 **                  Note: Both NFC Forum and Felica-Lite tags are supported by
3012 **                        this API.
3013 **                        RW_T3tDetectNDef() must be called before using this
3014 **
3015 **                  The RW_T3T_SET_READ_ONLY_CPLT_EVT event will be returned.
3016 **
3017 ** Returns          NFC_STATUS_OK if success
3018 **                  NFC_STATUS_FAILED if T3T is busy or other error
3019 **
3020 *****************************************************************************/
RW_T3tSetReadOnly(bool b_hard_lock)3021 tNFC_STATUS RW_T3tSetReadOnly(bool b_hard_lock) {
3022   tNFC_STATUS retval = NFC_STATUS_OK;
3023   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
3024   tRW_DATA evt_data;
3025   uint8_t rw_t3t_ndef_attrib_info[T3T_MSG_BLOCKSIZE];
3026   uint8_t* p;
3027   uint32_t tempU32 = 0;
3028   uint16_t checksum, i;
3029   uint8_t tempU8;
3030 
3031   DLOG_IF(INFO, nfc_debug_enabled)
3032       << StringPrintf("b_hard_lock=%d", b_hard_lock);
3033 
3034   /* Check if we are in valid state to handle this API */
3035   if (p_cb->rw_state != RW_T3T_STATE_IDLE) {
3036     LOG(ERROR) << StringPrintf("Error: invalid state to handle API (0x%x)",
3037                                p_cb->rw_state);
3038     return (NFC_STATUS_FAILED);
3039   }
3040 
3041   if (p_cb->ndef_attrib.status !=
3042       NFC_STATUS_OK) /* NDEF detection not performed yet? */
3043   {
3044     LOG(ERROR) << StringPrintf("Error: NDEF detection not performed yet");
3045     return (NFC_STATUS_NOT_INITIALIZED);
3046   }
3047 
3048   if ((!b_hard_lock) &&
3049       (p_cb->ndef_attrib.rwflag ==
3050        T3T_MSG_NDEF_RWFLAG_RO)) /* Tag's NDEF memory is read-only already */
3051   {
3052     evt_data.status = NFC_STATUS_OK;
3053     (*(rw_cb.p_cback))(RW_T3T_SET_READ_ONLY_CPLT_EVT, &evt_data);
3054     return (retval);
3055   } else {
3056     if (p_cb->cur_active_sc == T3T_SYSTEM_CODE_NDEF) {
3057       /* Tag previously responded for NDEF poll */
3058       if (p_cb->ndef_attrib.rwflag != T3T_MSG_NDEF_RWFLAG_RO) {
3059         /* First update attribute information block */
3060         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
3061             "%s - NDEF tag detected...update NDef attribution block.",
3062             __func__);
3063         p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_SOFT;
3064 
3065         p_cb->rw_substate = RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB;
3066 
3067         p = rw_t3t_ndef_attrib_info;
3068 
3069         UINT8_TO_STREAM(p, p_cb->ndef_attrib.version);
3070 
3071         /* Update NDEF info */
3072         UINT8_TO_STREAM(
3073             p, p_cb->ndef_attrib.nbr); /* NBr: number of blocks that can be read
3074                                           using one Check command */
3075         UINT8_TO_STREAM(p, p_cb->ndef_attrib.nbw); /* Nbw: number of blocks that
3076                                                       can be written using one
3077                                                       Update command */
3078         UINT16_TO_BE_STREAM(
3079             p, p_cb->ndef_attrib.nmaxb); /* Nmaxb: maximum number of blocks
3080                                             available for NDEF data */
3081         UINT32_TO_BE_STREAM(p, tempU32);
3082         UINT8_TO_STREAM(
3083             p, p_cb->ndef_attrib.writef); /* WriteFlag: 00h if writing
3084                                              data finished; 0Fh if
3085                                              writing data in progress */
3086         UINT8_TO_STREAM(p, 0x00);         /* RWFlag: 00h NDEF is read-only */
3087 
3088         tempU8 = (uint8_t)(p_cb->ndef_attrib.ln >> 16);
3089         /* Get length (3-byte, big-endian) */
3090         UINT8_TO_STREAM(p, tempU8);                   /* Ln: high-byte */
3091         UINT16_TO_BE_STREAM(p, p_cb->ndef_attrib.ln); /* Ln: lo-word */
3092 
3093         /* Calculate and append Checksum */
3094         checksum = 0;
3095         for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) {
3096           checksum += rw_t3t_ndef_attrib_info[i];
3097         }
3098         UINT16_TO_BE_STREAM(p, checksum);
3099 
3100         retval =
3101             rw_t3t_update_block(p_cb, 0, (uint8_t*)rw_t3t_ndef_attrib_info);
3102       }
3103     } else {
3104       /* Poll tag, to see if Felica-Lite system is supported */
3105       retval = (tNFC_STATUS)nci_snd_t3t_polling(T3T_SYSTEM_CODE_FELICA_LITE,
3106                                                 T3T_POLL_RC_SC, 0);
3107       if (retval == NCI_STATUS_OK) {
3108         if (b_hard_lock)
3109           p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_HARD;
3110         else
3111           p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_SOFT;
3112         p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
3113         p_cb->cur_poll_rc = T3T_POLL_RC_SC;
3114         p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
3115         p_cb->rw_substate = RW_T3T_SRO_SST_POLL_FELICA_LITE;
3116         p_cb->flags |= RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP;
3117 
3118         /* start timer for waiting for responses */
3119         rw_t3t_start_poll_timer(p_cb);
3120       }
3121     }
3122   }
3123   return (retval);
3124 }
3125