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