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