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