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