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