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