blob: fd0bbdff993f6633ff8360ea82908b3c8e1020e6 [file] [log] [blame]
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001/******************************************************************************
2 *
Evan Chue9629ba2014-01-31 11:18:47 -05003 * Copyright (C) 2010-2014 Broadcom Corporation
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08004 *
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 4 tag in Reader/Writer
22 * mode.
23 *
24 ******************************************************************************/
25#include <string.h>
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080026
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080027#include <android-base/stringprintf.h>
28#include <base/logging.h>
29
30#include "nfc_target.h"
31
32#include "bt_types.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080033#include "nfc_api.h"
34#include "nfc_int.h"
35#include "rw_api.h"
36#include "rw_int.h"
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080037#include "trace_api.h"
38
39using android::base::StringPrintf;
40
41extern bool nfc_debug_enabled;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080042
43/* main state */
Ruchi Kandoi46e6e282017-01-30 14:26:10 -080044/* T4T is not activated */
45#define RW_T4T_STATE_NOT_ACTIVATED 0x00
46/* waiting for upper layer API */
47#define RW_T4T_STATE_IDLE 0x01
48/* performing NDEF detection precedure */
49#define RW_T4T_STATE_DETECT_NDEF 0x02
50/* performing read NDEF procedure */
51#define RW_T4T_STATE_READ_NDEF 0x03
52/* performing update NDEF procedure */
53#define RW_T4T_STATE_UPDATE_NDEF 0x04
54/* checking presence of tag */
55#define RW_T4T_STATE_PRESENCE_CHECK 0x05
56/* convert tag to read only */
57#define RW_T4T_STATE_SET_READ_ONLY 0x06
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080058
Ruchi Kandoi46e6e282017-01-30 14:26:10 -080059/* performing NDEF format */
60#define RW_T4T_STATE_NDEF_FORMAT 0x07
Jizhou Liao94f37742015-06-03 12:31:03 -070061
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080062/* sub state */
Ruchi Kandoi46e6e282017-01-30 14:26:10 -080063/* waiting for response of selecting AID */
64#define RW_T4T_SUBSTATE_WAIT_SELECT_APP 0x00
65/* waiting for response of selecting CC */
66#define RW_T4T_SUBSTATE_WAIT_SELECT_CC 0x01
67/* waiting for response of reading CC */
68#define RW_T4T_SUBSTATE_WAIT_CC_FILE 0x02
69/* waiting for response of selecting NDEF */
70#define RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE 0x03
71/* waiting for response of reading NLEN */
72#define RW_T4T_SUBSTATE_WAIT_READ_NLEN 0x04
73/* waiting for response of reading file */
74#define RW_T4T_SUBSTATE_WAIT_READ_RESP 0x05
75/* waiting for response of updating file */
76#define RW_T4T_SUBSTATE_WAIT_UPDATE_RESP 0x06
77/* waiting for response of updating NLEN */
78#define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN 0x07
79/* waiting for response of updating CC */
80#define RW_T4T_SUBSTATE_WAIT_UPDATE_CC 0x08
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080081
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080082#define RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION 0x09
83#define RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION 0x0A
84#define RW_T4T_SUBSTATE_WAIT_GET_UID 0x0B
85#define RW_T4T_SUBSTATE_WAIT_CREATE_APP 0x0C
86#define RW_T4T_SUBSTATE_WAIT_CREATE_CC 0x0D
87#define RW_T4T_SUBSTATE_WAIT_CREATE_NDEF 0x0E
88#define RW_T4T_SUBSTATE_WAIT_WRITE_CC 0x0F
89#define RW_T4T_SUBSTATE_WAIT_WRITE_NDEF 0x10
Jizhou Liao94f37742015-06-03 12:31:03 -070090
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -070091static std::string rw_t4t_get_state_name(uint8_t state);
92static std::string rw_t4t_get_sub_state_name(uint8_t sub_state);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080093
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080094static bool rw_t4t_send_to_lower(NFC_HDR* p_c_apdu);
95static bool rw_t4t_select_file(uint16_t file_id);
96static bool rw_t4t_read_file(uint16_t offset, uint16_t length,
97 bool is_continue);
98static bool rw_t4t_update_nlen(uint16_t ndef_len);
99static bool rw_t4t_update_file(void);
100static bool rw_t4t_update_cc_to_readonly(void);
101static bool rw_t4t_select_application(uint8_t version);
102static bool rw_t4t_validate_cc_file(void);
Jizhou Liao94f37742015-06-03 12:31:03 -0700103
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800104static bool rw_t4t_get_hw_version(void);
105static bool rw_t4t_get_sw_version(void);
106static bool rw_t4t_create_app(void);
107static bool rw_t4t_select_app(void);
108static bool rw_t4t_create_ccfile(void);
109static bool rw_t4t_create_ndef(void);
110static bool rw_t4t_write_cc(void);
111static bool rw_t4t_write_ndef(void);
112static void rw_t4t_handle_error(tNFC_STATUS status, uint8_t sw1, uint8_t sw2);
113static void rw_t4t_sm_detect_ndef(NFC_HDR* p_r_apdu);
114static void rw_t4t_sm_read_ndef(NFC_HDR* p_r_apdu);
115static void rw_t4t_sm_update_ndef(NFC_HDR* p_r_apdu);
116static void rw_t4t_sm_set_readonly(NFC_HDR* p_r_apdu);
117static void rw_t4t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
118 tNFC_CONN* p_data);
119static void rw_t4t_sm_ndef_format(NFC_HDR* p_r_apdu);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800120
121/*******************************************************************************
122**
123** Function rw_t4t_send_to_lower
124**
125** Description Send C-APDU to lower layer
126**
127** Returns TRUE if success
128**
129*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800130static bool rw_t4t_send_to_lower(NFC_HDR* p_c_apdu) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800131 if (NFC_SendData(NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700132 LOG(ERROR) << StringPrintf("failed");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800133 return false;
134 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800135
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800136 nfc_start_quick_timer(&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE,
137 (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
Jizhou Liao94f37742015-06-03 12:31:03 -0700138
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800139 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700140}
141
142/*******************************************************************************
143**
144** Function rw_t4t_get_hw_version
145**
146** Description Send get hw version cmd to peer
147**
148** Returns TRUE if success
149**
150*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800151static bool rw_t4t_get_hw_version(void) {
152 NFC_HDR* p_c_apdu;
153 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700154
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800155 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700156
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800157 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700158 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800159 return false;
160 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700161
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800162 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
163 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700164
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800165 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
166 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_GET_HW_VERSION);
167 UINT16_TO_BE_STREAM(p, 0x0000);
168 UINT8_TO_BE_FIELD(p, 0x00);
Jizhou Liao94f37742015-06-03 12:31:03 -0700169
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800170 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
Jizhou Liao94f37742015-06-03 12:31:03 -0700171
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800172 if (!rw_t4t_send_to_lower(p_c_apdu)) {
173 return false;
174 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700175
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800176 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700177}
178
179/*******************************************************************************
180**
181** Function rw_t4t_get_sw_version
182**
183** Description Send get sw version cmd to peer
184**
185** Returns TRUE if success
186**
187*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800188static bool rw_t4t_get_sw_version(void) {
189 NFC_HDR* p_c_apdu;
190 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700191
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800192 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700193
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800194 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700195 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800196 return false;
197 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700198
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800199 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
200 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700201
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800202 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
203 UINT8_TO_BE_STREAM(p, T4T_ADDI_FRAME_RESP);
204 UINT16_TO_BE_STREAM(p, 0x0000);
205 UINT8_TO_BE_FIELD(p, 0x00);
Jizhou Liao94f37742015-06-03 12:31:03 -0700206
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800207 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
Jizhou Liao94f37742015-06-03 12:31:03 -0700208
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800209 if (!rw_t4t_send_to_lower(p_c_apdu)) {
210 return false;
211 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700212
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800213 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700214}
215
216/*******************************************************************************
217**
218** Function rw_t4t_update_version_details
219**
220** Description Updates the size of the card
221**
222** Returns TRUE if success
223**
224*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800225static bool rw_t4t_update_version_details(NFC_HDR* p_r_apdu) {
226 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
227 uint8_t* p;
228 uint16_t major_version, minor_version;
Jizhou Liao94f37742015-06-03 12:31:03 -0700229
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800230 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
231 major_version = *(p + 3);
232 minor_version = *(p + 4);
Jizhou Liao94f37742015-06-03 12:31:03 -0700233
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800234 if ((T4T_DESEV0_MAJOR_VERSION == major_version) &&
235 (T4T_DESEV0_MINOR_VERSION == minor_version)) {
236 p_t4t->card_size = 0xEDE;
237 } else if (major_version >= T4T_DESEV1_MAJOR_VERSION) {
238 p_t4t->card_type = T4T_TYPE_DESFIRE_EV1;
239 switch (*(p + 5)) {
240 case T4T_SIZE_IDENTIFIER_2K:
241 p_t4t->card_size = 2048;
242 break;
243 case T4T_SIZE_IDENTIFIER_4K:
244 p_t4t->card_size = 4096;
245 break;
246 case T4T_SIZE_IDENTIFIER_8K:
247 p_t4t->card_size = 7680;
248 break;
249 default:
Ruchi Kandoi4a179642017-01-04 10:04:48 -0800250 return false;
Jizhou Liao94f37742015-06-03 12:31:03 -0700251 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800252 } else {
253 return false;
254 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700255
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800256 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700257}
258
259/*******************************************************************************
260**
261** Function rw_t4t_get_uid_details
262**
263** Description Send get uid cmd to peer
264**
265** Returns TRUE if success
266**
267*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800268static bool rw_t4t_get_uid_details(void) {
269 NFC_HDR* p_c_apdu;
270 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700271
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800272 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700273
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800274 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700275 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800276 return false;
277 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700278
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800279 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
280 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700281
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800282 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
283 UINT8_TO_BE_STREAM(p, T4T_ADDI_FRAME_RESP);
284 UINT16_TO_BE_STREAM(p, 0x0000);
285 UINT8_TO_BE_FIELD(p, 0x00);
Jizhou Liao94f37742015-06-03 12:31:03 -0700286
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800287 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
Jizhou Liao94f37742015-06-03 12:31:03 -0700288
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800289 if (!rw_t4t_send_to_lower(p_c_apdu)) {
290 return false;
291 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700292
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800293 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700294}
295
296/*******************************************************************************
297**
298** Function rw_t4t_create_app
299**
300** Description Send create application cmd to peer
301**
302** Returns TRUE if success
303**
304*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800305static bool rw_t4t_create_app(void) {
306 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
307 NFC_HDR* p_c_apdu;
308 uint8_t* p;
309 uint8_t df_name[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
Jizhou Liao94f37742015-06-03 12:31:03 -0700310
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800311 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700312
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800313 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700314 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800315 return false;
316 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700317
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800318 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
319 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700320
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800321 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
322 UINT8_TO_BE_STREAM(p, T4T_CMD_CREATE_AID);
323 UINT16_TO_BE_STREAM(p, 0x0000);
324 if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) {
325 UINT8_TO_BE_STREAM(p, (T4T_CMD_MAX_HDR_SIZE + sizeof(df_name) + 2));
326 UINT24_TO_BE_STREAM(p, T4T_DES_EV1_NFC_APP_ID);
327 UINT16_TO_BE_STREAM(p, 0x0F21); /*Key settings and no.of keys */
328 UINT16_TO_BE_STREAM(p, 0x05E1); /* ISO file ID */
329 ARRAY_TO_BE_STREAM(p, df_name, (int)sizeof(df_name)); /*DF file name */
330 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
331 p_c_apdu->len = 20;
332 } else {
333 UINT8_TO_BE_STREAM(p, T4T_CMD_MAX_HDR_SIZE);
334 UINT24_TO_BE_STREAM(p, T4T_DES_EV0_NFC_APP_ID);
335 UINT16_TO_BE_STREAM(p, 0x0F01); /*Key settings and no.of keys */
336 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
337 p_c_apdu->len = 11;
338 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700339
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800340 if (!rw_t4t_send_to_lower(p_c_apdu)) {
341 return false;
342 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700343
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800344 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700345}
346
347/*******************************************************************************
348**
349** Function rw_t4t_select_app
350**
351** Description Select application cmd to peer
352**
353** Returns TRUE if success
354**
355*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800356static bool rw_t4t_select_app(void) {
357 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
358 NFC_HDR* p_c_apdu;
359 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700360
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800361 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700362
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800363 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700364 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800365 return false;
366 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700367
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800368 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
369 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700370
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800371 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
372 UINT8_TO_BE_STREAM(p, T4T_CMD_SELECT_APP);
373 UINT16_TO_BE_STREAM(p, 0x0000);
374 UINT8_TO_BE_STREAM(p, 0x03); /* Lc: length of wrapped data */
375 if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) {
376 UINT24_TO_BE_STREAM(p, T4T_DES_EV1_NFC_APP_ID);
377 } else {
378 UINT24_TO_BE_STREAM(p, T4T_DES_EV0_NFC_APP_ID);
379 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700380
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800381 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
Jizhou Liao94f37742015-06-03 12:31:03 -0700382
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800383 p_c_apdu->len = 9;
Jizhou Liao94f37742015-06-03 12:31:03 -0700384
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800385 if (!rw_t4t_send_to_lower(p_c_apdu)) {
386 return false;
387 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700388
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800389 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700390}
391
392/*******************************************************************************
393**
394** Function rw_t4t_create_ccfile
395**
396** Description create capability container file cmd to peer
397**
398** Returns TRUE if success
399**
400*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800401static bool rw_t4t_create_ccfile(void) {
402 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
403 NFC_HDR* p_c_apdu;
404 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700405
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800406 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700407
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800408 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700409 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800410 return false;
411 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700412
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800413 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
414 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700415
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800416 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
417 UINT8_TO_BE_STREAM(p, T4T_CMD_CREATE_DATAFILE);
418 UINT16_TO_BE_STREAM(p, 0x0000);
419 if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) {
420 UINT8_TO_BE_STREAM(p, 0x09); /* Lc: length of wrapped data */
421 UINT8_TO_BE_STREAM(p, 0x01); /* EV1 CC file id */
422 UINT16_TO_BE_STREAM(p, 0x03E1); /* ISO file id */
423 } else {
424 UINT8_TO_BE_STREAM(p, 0x07); /* Lc: length of wrapped data */
425 UINT8_TO_BE_STREAM(p, 0x03); /* DESFire CC file id */
426 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700427
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800428 UINT8_TO_BE_STREAM(p, 0x00); /* COMM settings */
429 UINT16_TO_BE_STREAM(p, 0xEEEE); /* Access rights */
430 UINT24_TO_BE_STREAM(p, 0x0F0000); /* Set file size */
431 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
Jizhou Liao94f37742015-06-03 12:31:03 -0700432
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800433 p_c_apdu->len = (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) ? 15 : 13;
Jizhou Liao94f37742015-06-03 12:31:03 -0700434
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800435 if (!rw_t4t_send_to_lower(p_c_apdu)) {
436 return false;
437 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700438
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800439 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700440}
441
442/*******************************************************************************
443**
444** Function rw_t4t_create_ndef
445**
446** Description creates an ndef file cmd to peer
447**
448** Returns TRUE if success
449**
450*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800451static bool rw_t4t_create_ndef(void) {
452 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
453 NFC_HDR* p_c_apdu;
454 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700455
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800456 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700457
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800458 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700459 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800460 return false;
461 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700462
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800463 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
464 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700465
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800466 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
467 UINT8_TO_BE_STREAM(p, T4T_CMD_CREATE_DATAFILE);
468 UINT16_TO_BE_STREAM(p, 0x0000);
469 if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) {
470 UINT8_TO_BE_STREAM(p, 0x09); /* Lc: length of wrapped data */
471 UINT8_TO_BE_STREAM(p, 0x02); /* DESFEv1 NDEF file id */
472 UINT16_TO_BE_STREAM(p, 0x04E1); /* ISO file id */
473 } else {
474 UINT8_TO_BE_STREAM(p, 0x07);
475 UINT8_TO_BE_STREAM(p, 0x04); /* DESF4 NDEF file id */
476 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700477
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800478 UINT8_TO_BE_STREAM(p, 0x00); /* COMM settings */
479 UINT16_TO_BE_STREAM(p, 0xEEEE); /* Access rights */
480 UINT16_TO_STREAM(p, p_t4t->card_size);
481 UINT8_TO_BE_STREAM(p, 0x00); /* Set card size */
482 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
Jizhou Liao94f37742015-06-03 12:31:03 -0700483
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800484 p_c_apdu->len = (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) ? 15 : 13;
Jizhou Liao94f37742015-06-03 12:31:03 -0700485
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800486 if (!rw_t4t_send_to_lower(p_c_apdu)) {
487 return false;
488 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700489
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800490 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700491}
492
493/*******************************************************************************
494**
495** Function rw_t4t_write_cc
496**
497** Description sends write cc file cmd to peer
498**
499** Returns TRUE if success
500**
501*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800502static bool rw_t4t_write_cc(void) {
503 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
504 NFC_HDR* p_c_apdu;
505 uint8_t* p;
506 uint8_t CCFileBytes[] = {0x00, 0x0F, 0x10, 0x00, 0x3B, 0x00, 0x34, 0x04,
507 0x06, 0xE1, 0x04, 0x04, 0x00, 0x00, 0x00};
Jizhou Liao94f37742015-06-03 12:31:03 -0700508
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800509 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700510
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800511 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700512 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800513 return false;
514 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700515
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800516 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
517 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700518
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800519 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
520 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_WRITE);
521 UINT16_TO_BE_STREAM(p, 0x0000);
522 UINT8_TO_BE_STREAM(p, 0x16); /* Lc: length of wrapped data */
523 if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) {
524 CCFileBytes[2] = 0x20;
525 CCFileBytes[11] = p_t4t->card_size >> 8;
526 CCFileBytes[12] = (uint8_t)p_t4t->card_size;
527 UINT8_TO_BE_STREAM(p, 0x01); /* CC file id */
528 } else {
529 UINT8_TO_BE_STREAM(p, 0x03);
530 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700531
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800532 UINT24_TO_BE_STREAM(p, 0x000000); /* Set the offset */
533 UINT24_TO_BE_STREAM(p, 0x0F0000); /* Set available length */
534 ARRAY_TO_BE_STREAM(p, CCFileBytes, (int)sizeof(CCFileBytes));
535 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
Jizhou Liao94f37742015-06-03 12:31:03 -0700536
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800537 p_c_apdu->len = 28;
Jizhou Liao94f37742015-06-03 12:31:03 -0700538
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800539 if (!rw_t4t_send_to_lower(p_c_apdu)) {
540 return false;
541 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700542
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800543 return true;
Jizhou Liao94f37742015-06-03 12:31:03 -0700544}
545
546/*******************************************************************************
547**
548** Function rw_t4t_write_ndef
549**
550** Description sends write ndef file cmd to peer
551**
552** Returns TRUE if success
553**
554*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800555static bool rw_t4t_write_ndef(void) {
556 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
557 NFC_HDR* p_c_apdu;
558 uint8_t* p;
Jizhou Liao94f37742015-06-03 12:31:03 -0700559
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800560 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Jizhou Liao94f37742015-06-03 12:31:03 -0700561
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800562 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700563 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800564 return false;
565 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700566
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800567 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
568 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -0700569
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800570 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_CLASS);
571 UINT8_TO_BE_STREAM(p, T4T_CMD_DES_WRITE);
572 UINT16_TO_BE_STREAM(p, 0x0000);
573 UINT8_TO_BE_STREAM(p, 0x09); /* Lc: length of wrapped data */
574 if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) {
575 UINT8_TO_BE_STREAM(p, 0x02); /* DESFEv1 Ndef file id */
576 } else {
577 UINT8_TO_BE_STREAM(p, 0x04);
578 }
Jizhou Liao94f37742015-06-03 12:31:03 -0700579
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800580 UINT24_TO_BE_STREAM(p, 0x000000); /* Set the offset */
581 UINT24_TO_BE_STREAM(p, 0x020000); /* Set available length */
582 UINT16_TO_BE_STREAM(p, 0x0000); /* Ndef file bytes */
583 UINT8_TO_BE_STREAM(p, 0x00); /* Le */
Jizhou Liao94f37742015-06-03 12:31:03 -0700584
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800585 p_c_apdu->len = 15;
Jizhou Liao94f37742015-06-03 12:31:03 -0700586
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800587 if (!rw_t4t_send_to_lower(p_c_apdu)) {
588 return false;
589 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800590
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800591 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800592}
593
594/*******************************************************************************
595**
596** Function rw_t4t_select_file
597**
598** Description Send Select Command (by File ID) to peer
599**
600** Returns TRUE if success
601**
602*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800603static bool rw_t4t_select_file(uint16_t file_id) {
604 NFC_HDR* p_c_apdu;
605 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800606
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700607 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("File ID:0x%04X", file_id);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800608
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800609 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800610
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800611 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700612 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800613 return false;
614 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800615
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800616 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
617 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800618
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800619 UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
620 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_SELECT);
621 UINT8_TO_BE_STREAM(p, T4T_CMD_P1_SELECT_BY_FILE_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800622
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800623 /* if current version mapping is V2.0 */
624 if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0) {
625 UINT8_TO_BE_STREAM(p, T4T_CMD_P2_FIRST_OR_ONLY_0CH);
626 } else /* version 1.0 */
627 {
628 UINT8_TO_BE_STREAM(p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
629 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800630
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800631 UINT8_TO_BE_STREAM(p, T4T_FILE_ID_SIZE);
632 UINT16_TO_BE_STREAM(p, file_id);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800633
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800634 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800635
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800636 if (!rw_t4t_send_to_lower(p_c_apdu)) {
637 return false;
638 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800639
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800640 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800641}
642
643/*******************************************************************************
644**
645** Function rw_t4t_read_file
646**
647** Description Send ReadBinary Command to peer
648**
649** Returns TRUE if success
650**
651*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800652static bool rw_t4t_read_file(uint16_t offset, uint16_t length,
653 bool is_continue) {
654 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
655 NFC_HDR* p_c_apdu;
656 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800657
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700658 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
659 "offset:%d, length:%d, is_continue:%d, ", offset, length, is_continue);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800660
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800661 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800662
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800663 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700664 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800665 return false;
666 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800667
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800668 /* if this is the first reading */
669 if (is_continue == false) {
670 /* initialise starting offset and total length */
671 /* these will be updated when receiving response */
672 p_t4t->rw_offset = offset;
673 p_t4t->rw_length = length;
674 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800675
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800676 /* adjust reading length if payload is bigger than max size per single command
677 */
678 if (length > p_t4t->max_read_size) {
679 length = (uint8_t)(p_t4t->max_read_size);
680 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800681
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800682 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
683 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800684
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800685 UINT8_TO_BE_STREAM(p, (T4T_CMD_CLASS | rw_cb.tcb.t4t.channel));
686 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_READ_BINARY);
687 UINT16_TO_BE_STREAM(p, offset);
688 UINT8_TO_BE_STREAM(p, length); /* Le */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800689
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800690 p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800691
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800692 if (!rw_t4t_send_to_lower(p_c_apdu)) {
693 return false;
694 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800695
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800696 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800697}
698
699/*******************************************************************************
700**
701** Function rw_t4t_update_nlen
702**
703** Description Send UpdateBinary Command to update NLEN to peer
704**
705** Returns TRUE if success
706**
707*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800708static bool rw_t4t_update_nlen(uint16_t ndef_len) {
709 NFC_HDR* p_c_apdu;
710 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800711
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700712 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("NLEN:%d", ndef_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800713
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800714 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800715
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800716 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700717 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800718 return false;
719 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800720
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800721 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
722 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800723
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800724 UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
725 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY);
726 UINT16_TO_BE_STREAM(p, 0x0000); /* offset for NLEN */
727 UINT8_TO_BE_STREAM(p, T4T_FILE_LENGTH_SIZE);
728 UINT16_TO_BE_STREAM(p, ndef_len);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800729
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800730 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800731
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800732 if (!rw_t4t_send_to_lower(p_c_apdu)) {
733 return false;
734 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800735
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800736 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800737}
738
739/*******************************************************************************
740**
741** Function rw_t4t_update_file
742**
743** Description Send UpdateBinary Command to peer
744**
745** Returns TRUE if success
746**
747*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800748static bool rw_t4t_update_file(void) {
749 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
750 NFC_HDR* p_c_apdu;
751 uint8_t* p;
752 uint16_t length;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800753
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700754 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
755 "rw_offset:%d, rw_length:%d", p_t4t->rw_offset, p_t4t->rw_length);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800756
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800757 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800758
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800759 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700760 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800761 return false;
762 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800763
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800764 /* try to send all of remaining data */
765 length = p_t4t->rw_length;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800766
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800767 /* adjust updating length if payload is bigger than max size per single
768 * command */
769 if (length > p_t4t->max_update_size) {
770 length = (uint8_t)(p_t4t->max_update_size);
771 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800772
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800773 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
774 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800775
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800776 UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
777 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY);
778 UINT16_TO_BE_STREAM(p, p_t4t->rw_offset);
779 UINT8_TO_BE_STREAM(p, length);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800780
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800781 memcpy(p, p_t4t->p_update_data, length);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800782
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800783 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800784
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800785 if (!rw_t4t_send_to_lower(p_c_apdu)) {
786 return false;
787 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800788
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800789 /* adjust offset, length and pointer for remaining data */
790 p_t4t->rw_offset += length;
791 p_t4t->rw_length -= length;
792 p_t4t->p_update_data += length;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800793
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800794 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800795}
796
797/*******************************************************************************
798**
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700799** Function rw_t4t_update_cc_to_readonly
800**
801** Description Send UpdateBinary Command for changing Write access
802**
803** Returns TRUE if success
804**
805*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800806static bool rw_t4t_update_cc_to_readonly(void) {
807 NFC_HDR* p_c_apdu;
808 uint8_t* p;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700809
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700810 DLOG_IF(INFO, nfc_debug_enabled)
811 << StringPrintf("Remove Write access from CC");
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700812
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800813 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700814
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800815 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700816 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800817 return false;
818 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700819
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800820 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
821 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700822
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800823 /* Add Command Header */
824 UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
825 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY);
826 UINT16_TO_BE_STREAM(
827 p, (T4T_FC_TLV_OFFSET_IN_CC +
828 T4T_FC_WRITE_ACCESS_OFFSET_IN_TLV)); /* Offset for Read Write access
829 byte of CC */
830 UINT8_TO_BE_STREAM(
831 p, 1); /* Length of write access field in cc interms of bytes */
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700832
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800833 /* Remove Write access */
834 UINT8_TO_BE_STREAM(p, T4T_FC_NO_WRITE_ACCESS);
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700835
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800836 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + 1;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700837
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800838 if (!rw_t4t_send_to_lower(p_c_apdu)) {
839 return false;
840 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700841
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800842 return true;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -0700843}
844
845/*******************************************************************************
846**
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800847** Function rw_t4t_select_application
848**
849** Description Select Application
850**
851** NDEF Tag Application Select - C-APDU
852**
853** CLA INS P1 P2 Lc Data(AID) Le
854** V1.0: 00 A4 04 00 07 D2760000850100 -
855** V2.0: 00 A4 04 00 07 D2760000850101 00
856**
857** Returns TRUE if success
858**
859*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800860static bool rw_t4t_select_application(uint8_t version) {
861 NFC_HDR* p_c_apdu;
862 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800863
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700864 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("version:0x%X", version);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800865
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800866 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800867
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800868 if (!p_c_apdu) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700869 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800870 return false;
871 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800872
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800873 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
874 p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800875
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800876 UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
877 UINT8_TO_BE_STREAM(p, T4T_CMD_INS_SELECT);
878 UINT8_TO_BE_STREAM(p, T4T_CMD_P1_SELECT_BY_NAME);
879 UINT8_TO_BE_STREAM(p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800880
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800881 if (version == T4T_VERSION_1_0) /* this is for V1.0 */
882 {
883 UINT8_TO_BE_STREAM(p, T4T_V10_NDEF_TAG_AID_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800884
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800885 memcpy(p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800886
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800887 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN;
888 } else if (version == T4T_VERSION_2_0) /* this is for V2.0 */
889 {
890 UINT8_TO_BE_STREAM(p, T4T_V20_NDEF_TAG_AID_LEN);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800891
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800892 memcpy(p, t4t_v20_ndef_tag_aid, T4T_V20_NDEF_TAG_AID_LEN);
893 p += T4T_V20_NDEF_TAG_AID_LEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800894
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800895 UINT8_TO_BE_STREAM(p, 0x00); /* Le set to 0x00 */
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800896
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800897 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V20_NDEF_TAG_AID_LEN + 1;
898 } else {
899 return false;
900 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800901
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800902 if (!rw_t4t_send_to_lower(p_c_apdu)) {
903 return false;
904 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800905
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800906 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800907}
908
909/*******************************************************************************
910**
911** Function rw_t4t_validate_cc_file
912**
913** Description Validate CC file and mandatory NDEF TLV
914**
915** Returns TRUE if success
916**
917*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800918static bool rw_t4t_validate_cc_file(void) {
919 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800920
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700921 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800922
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800923 if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700924 LOG(ERROR) << StringPrintf("CCLEN (%d) is too short", p_t4t->cc_file.cclen);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800925 return false;
926 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800927
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800928 if (T4T_GET_MAJOR_VERSION(p_t4t->cc_file.version) !=
929 T4T_GET_MAJOR_VERSION(p_t4t->version)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700930 LOG(ERROR) << StringPrintf(
931 "Peer version (0x%02X) is matched to ours "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800932 "(0x%02X)",
933 p_t4t->cc_file.version, p_t4t->version);
934 return false;
935 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800936
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800937 if (p_t4t->cc_file.max_le < 0x000F) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700938 LOG(ERROR) << StringPrintf("MaxLe (%d) is too small",
939 p_t4t->cc_file.max_le);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800940 return false;
941 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800942
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800943 if (p_t4t->cc_file.max_lc < 0x0001) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700944 LOG(ERROR) << StringPrintf("MaxLc (%d) is too small",
945 p_t4t->cc_file.max_lc);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800946 return false;
947 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800948
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800949 if ((p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID) ||
950 (p_t4t->cc_file.ndef_fc.file_id == 0xE102) ||
951 (p_t4t->cc_file.ndef_fc.file_id == 0xE103) ||
952 ((p_t4t->cc_file.ndef_fc.file_id == 0x0000) &&
953 (p_t4t->cc_file.version == 0x20)) ||
954 (p_t4t->cc_file.ndef_fc.file_id == 0x3F00) ||
955 (p_t4t->cc_file.ndef_fc.file_id == 0x3FFF) ||
956 (p_t4t->cc_file.ndef_fc.file_id == 0xFFFF)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700957 LOG(ERROR) << StringPrintf("File ID (0x%04X) is invalid",
958 p_t4t->cc_file.ndef_fc.file_id);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800959 return false;
960 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800961
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800962 if ((p_t4t->cc_file.ndef_fc.max_file_size < 0x0005) ||
963 (p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700964 LOG(ERROR) << StringPrintf("max_file_size (%d) is reserved",
965 p_t4t->cc_file.ndef_fc.max_file_size);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800966 return false;
967 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800968
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800969 if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700970 LOG(ERROR) << StringPrintf("Read Access (0x%02X) is invalid",
971 p_t4t->cc_file.ndef_fc.read_access);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800972 return false;
973 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800974
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800975 if ((p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) &&
Ruchi Kandoiee980b72017-04-06 15:20:25 -0700976 (p_t4t->cc_file.ndef_fc.write_access < T4T_FC_WRITE_ACCESS_PROP_START)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700977 LOG(ERROR) << StringPrintf("Write Access (0x%02X) is invalid",
978 p_t4t->cc_file.ndef_fc.write_access);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800979 return false;
980 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800981
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800982 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800983}
984
985/*******************************************************************************
986**
987** Function rw_t4t_handle_error
988**
989** Description notify error to application and clean up
990**
991** Returns none
992**
993*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800994static void rw_t4t_handle_error(tNFC_STATUS status, uint8_t sw1, uint8_t sw2) {
995 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
996 tRW_DATA rw_data;
997 tRW_EVENT event;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800998
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700999 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1000 "status:0x%02X, sw1:0x%02X, sw2:0x%02X, "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001001 "state:0x%X",
1002 status, sw1, sw2, p_t4t->state);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001003
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001004 nfc_stop_quick_timer(&p_t4t->timer);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001005
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001006 if (rw_cb.p_cback) {
1007 rw_data.status = status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001008
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001009 rw_data.t4t_sw.sw1 = sw1;
1010 rw_data.t4t_sw.sw2 = sw2;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001011
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001012 switch (p_t4t->state) {
1013 case RW_T4T_STATE_DETECT_NDEF:
1014 rw_data.ndef.flags = RW_NDEF_FL_UNKNOWN;
1015 event = RW_T4T_NDEF_DETECT_EVT;
1016 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001017
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001018 case RW_T4T_STATE_READ_NDEF:
1019 event = RW_T4T_NDEF_READ_FAIL_EVT;
1020 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001021
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001022 case RW_T4T_STATE_UPDATE_NDEF:
1023 event = RW_T4T_NDEF_UPDATE_FAIL_EVT;
1024 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001025
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001026 case RW_T4T_STATE_PRESENCE_CHECK:
1027 event = RW_T4T_PRESENCE_CHECK_EVT;
1028 rw_data.status = NFC_STATUS_FAILED;
1029 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001030
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001031 case RW_T4T_STATE_SET_READ_ONLY:
1032 event = RW_T4T_SET_TO_RO_EVT;
1033 break;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001034
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001035 case RW_T4T_STATE_NDEF_FORMAT:
1036 event = RW_T4T_NDEF_FORMAT_CPLT_EVT;
1037 rw_data.status = NFC_STATUS_FAILED;
1038 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001039
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001040 default:
1041 event = RW_T4T_MAX_EVT;
1042 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001043 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001044
1045 p_t4t->state = RW_T4T_STATE_IDLE;
1046
1047 if (event != RW_T4T_MAX_EVT) {
1048 (*(rw_cb.p_cback))(event, &rw_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001049 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001050 } else {
1051 p_t4t->state = RW_T4T_STATE_IDLE;
1052 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001053}
1054
1055/*******************************************************************************
1056**
Jizhou Liao94f37742015-06-03 12:31:03 -07001057** Function rw_t4t_sm_ndef_format
1058**
1059** Description State machine for NDEF format procedure
1060**
1061** Returns none
1062**
1063*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001064static void rw_t4t_sm_ndef_format(NFC_HDR* p_r_apdu) {
1065 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
Ruchi Kandoi9ba6d242017-10-13 16:07:01 -07001066 uint8_t* p;
1067 uint16_t status_words;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001068 tRW_DATA rw_data;
Jizhou Liao94f37742015-06-03 12:31:03 -07001069
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001070 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1071 "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
1072 p_t4t->sub_state);
Jizhou Liao94f37742015-06-03 12:31:03 -07001073
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001074 /* get status words */
1075 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
Jizhou Liao94f37742015-06-03 12:31:03 -07001076
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001077 switch (p_t4t->sub_state) {
Jizhou Liao94f37742015-06-03 12:31:03 -07001078 case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001079 p += (p_r_apdu->len - 1);
1080 if (*(p) == T4T_ADDI_FRAME_RESP) {
1081 if (!rw_t4t_get_sw_version()) {
1082 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1083 } else {
1084 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION;
Jizhou Liao94f37742015-06-03 12:31:03 -07001085 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001086 } else {
1087 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1088 }
1089 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001090
1091 case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001092 p += (p_r_apdu->len - 1);
1093 if (*(p) == T4T_ADDI_FRAME_RESP) {
1094 if (!rw_t4t_update_version_details(p_r_apdu)) {
1095 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
Jizhou Liao94f37742015-06-03 12:31:03 -07001096 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001097
1098 if (!rw_t4t_get_uid_details()) {
1099 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
Jizhou Liao94f37742015-06-03 12:31:03 -07001100 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001101
1102 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_UID;
1103 } else {
1104 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1105 }
1106 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001107
1108 case RW_T4T_SUBSTATE_WAIT_GET_UID:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001109 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1110 BE_STREAM_TO_UINT16(status_words, p);
1111 if (status_words != 0x9100) {
1112 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1113 } else {
1114 if (!rw_t4t_create_app()) {
1115 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1116 } else {
1117 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_APP;
Jizhou Liao94f37742015-06-03 12:31:03 -07001118 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001119 }
1120 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001121
1122 case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001123 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1124 BE_STREAM_TO_UINT16(status_words, p);
1125 if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1126 {
1127 status_words = 0x9100;
1128 }
Jizhou Liao94f37742015-06-03 12:31:03 -07001129
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001130 if (status_words != 0x9100) {
1131 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1132 } else {
1133 if (!rw_t4t_select_app()) {
1134 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1135 } else {
1136 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
Jizhou Liao94f37742015-06-03 12:31:03 -07001137 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001138 }
1139 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001140
1141 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001142 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1143 BE_STREAM_TO_UINT16(status_words, p);
1144 if (status_words != 0x9100) {
1145 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1146 } else {
1147 if (!rw_t4t_create_ccfile()) {
1148 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1149 } else {
1150 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_CC;
Jizhou Liao94f37742015-06-03 12:31:03 -07001151 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001152 }
1153 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001154
1155 case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001156 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1157 BE_STREAM_TO_UINT16(status_words, p);
1158 if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1159 {
1160 status_words = 0x9100;
1161 }
Jizhou Liao94f37742015-06-03 12:31:03 -07001162
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001163 if (status_words != 0x9100) {
1164 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1165 } else {
1166 if (!rw_t4t_create_ndef()) {
1167 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1168 } else {
1169 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_NDEF;
Jizhou Liao94f37742015-06-03 12:31:03 -07001170 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001171 }
1172 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001173
1174 case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001175 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1176 BE_STREAM_TO_UINT16(status_words, p);
1177 if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1178 {
1179 status_words = 0x9100;
1180 }
Jizhou Liao94f37742015-06-03 12:31:03 -07001181
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001182 if (status_words != 0x9100) {
1183 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1184 } else {
1185 if (!rw_t4t_write_cc()) {
1186 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1187 } else {
1188 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_CC;
Jizhou Liao94f37742015-06-03 12:31:03 -07001189 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001190 }
1191 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001192
1193 case RW_T4T_SUBSTATE_WAIT_WRITE_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001194 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1195 BE_STREAM_TO_UINT16(status_words, p);
1196 if (status_words != 0x9100) {
1197 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1198 } else {
1199 if (!rw_t4t_write_ndef()) {
1200 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1201 } else {
1202 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_NDEF;
Jizhou Liao94f37742015-06-03 12:31:03 -07001203 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001204 }
1205 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001206
1207 case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001208 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1209 BE_STREAM_TO_UINT16(status_words, p);
1210 if (status_words != 0x9100) {
1211 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1212 } else {
1213 p_t4t->state = RW_T4T_STATE_IDLE;
1214 if (rw_cb.p_cback) {
1215 rw_data.ndef.status = NFC_STATUS_OK;
1216 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
1217 rw_data.ndef.max_size = p_t4t->card_size;
1218 rw_data.ndef.cur_size = 0x00;
Jizhou Liao94f37742015-06-03 12:31:03 -07001219
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001220 (*(rw_cb.p_cback))(RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
Jizhou Liao94f37742015-06-03 12:31:03 -07001221
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001222 DLOG_IF(INFO, nfc_debug_enabled)
1223 << StringPrintf("Sent RW_T4T_NDEF_FORMAT_CPLT_EVT");
Jizhou Liao94f37742015-06-03 12:31:03 -07001224 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001225 }
1226 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001227
1228 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001229 LOG(ERROR) << StringPrintf("unknown sub_state=%d", p_t4t->sub_state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001230 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1231 break;
1232 }
Jizhou Liao94f37742015-06-03 12:31:03 -07001233}
1234
1235/*******************************************************************************
1236**
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001237** Function rw_t4t_sm_detect_ndef
1238**
1239** Description State machine for NDEF detection procedure
1240**
1241** Returns none
1242**
1243*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001244static void rw_t4t_sm_detect_ndef(NFC_HDR* p_r_apdu) {
1245 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1246 uint8_t *p, type, length;
1247 uint16_t status_words, nlen;
1248 tRW_DATA rw_data;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001249
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001250 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1251 "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
1252 p_t4t->sub_state);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001253
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001254 /* get status words */
1255 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1256 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1257 BE_STREAM_TO_UINT16(status_words, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001258
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001259 if (status_words != T4T_RSP_CMD_CMPLTED) {
1260 /* try V1.0 after failing of V2.0 */
1261 if ((p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP) &&
1262 (p_t4t->version == T4T_VERSION_2_0)) {
1263 p_t4t->version = T4T_VERSION_1_0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001264
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001265 DLOG_IF(INFO, nfc_debug_enabled)
1266 << StringPrintf("retry with version=0x%02X", p_t4t->version);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001267
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001268 if (!rw_t4t_select_application(T4T_VERSION_1_0)) {
1269 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1270 }
1271 return;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001272 }
1273
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001274 p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1275 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1276 return;
1277 }
1278
1279 switch (p_t4t->sub_state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001280 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1281
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001282 /* NDEF Tag application has been selected then select CC file */
1283 if (!rw_t4t_select_file(T4T_CC_FILE_ID)) {
1284 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1285 } else {
1286 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1287 }
1288 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001289
1290 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1291
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001292 /* CC file has been selected then read mandatory part of CC file */
1293 if (!rw_t4t_read_file(0x00, T4T_CC_FILE_MIN_LEN, false)) {
1294 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1295 } else {
1296 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
1297 }
1298 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001299
1300 case RW_T4T_SUBSTATE_WAIT_CC_FILE:
1301
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001302 /* CC file has been read then validate and select mandatory NDEF file */
1303 if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE) {
1304 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001305
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001306 BE_STREAM_TO_UINT16(p_t4t->cc_file.cclen, p);
1307 BE_STREAM_TO_UINT8(p_t4t->cc_file.version, p);
1308 BE_STREAM_TO_UINT16(p_t4t->cc_file.max_le, p);
1309 BE_STREAM_TO_UINT16(p_t4t->cc_file.max_lc, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001310
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001311 BE_STREAM_TO_UINT8(type, p);
1312 BE_STREAM_TO_UINT8(length, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001313
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001314 if ((type == T4T_NDEF_FILE_CONTROL_TYPE) &&
1315 (length == T4T_FILE_CONTROL_LENGTH)) {
1316 BE_STREAM_TO_UINT16(p_t4t->cc_file.ndef_fc.file_id, p);
1317 BE_STREAM_TO_UINT16(p_t4t->cc_file.ndef_fc.max_file_size, p);
1318 BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.read_access, p);
1319 BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.write_access, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001320
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001321 DLOG_IF(INFO, nfc_debug_enabled)
1322 << StringPrintf("Capability Container (CC) file");
1323 DLOG_IF(INFO, nfc_debug_enabled)
1324 << StringPrintf(" CCLEN: 0x%04X", p_t4t->cc_file.cclen);
1325 DLOG_IF(INFO, nfc_debug_enabled)
1326 << StringPrintf(" Version:0x%02X", p_t4t->cc_file.version);
1327 DLOG_IF(INFO, nfc_debug_enabled)
1328 << StringPrintf(" MaxLe: 0x%04X", p_t4t->cc_file.max_le);
1329 DLOG_IF(INFO, nfc_debug_enabled)
1330 << StringPrintf(" MaxLc: 0x%04X", p_t4t->cc_file.max_lc);
1331 DLOG_IF(INFO, nfc_debug_enabled)
1332 << StringPrintf(" NDEF File Control TLV");
1333 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1334 " FileID: 0x%04X", p_t4t->cc_file.ndef_fc.file_id);
1335 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1336 " MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size);
1337 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1338 " ReadAccess: 0x%02X", p_t4t->cc_file.ndef_fc.read_access);
1339 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1340 " WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001341
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001342 if (rw_t4t_validate_cc_file()) {
1343 if (!rw_t4t_select_file(p_t4t->cc_file.ndef_fc.file_id)) {
1344 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1345 } else {
1346 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001347 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001348 break;
1349 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001350 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001351 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001352
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001353 /* invalid response or CC file */
1354 p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1355 rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
1356 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001357
1358 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1359
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001360 /* NDEF file has been selected then read the first 2 bytes (NLEN) */
1361 if (!rw_t4t_read_file(0, T4T_FILE_LENGTH_SIZE, false)) {
1362 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1363 } else {
1364 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
1365 }
1366 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001367
1368 case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
1369
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001370 /* NLEN has been read then report upper layer */
1371 if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE) {
1372 /* get length of NDEF */
1373 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1374 BE_STREAM_TO_UINT16(nlen, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001375
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001376 if (nlen <=
1377 p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE) {
1378 p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001379
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001380 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) {
1381 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1382 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001383
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001384 /* Get max bytes to read per command */
1385 if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ) {
1386 p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ;
1387 } else {
1388 p_t4t->max_read_size = p_t4t->cc_file.max_le;
1389 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001390
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001391 /* Le: valid range is 0x01 to 0xFF */
1392 if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE) {
1393 p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
1394 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001395
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001396 /* Get max bytes to update per command */
1397 if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE) {
1398 p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE;
1399 } else {
1400 p_t4t->max_update_size = p_t4t->cc_file.max_lc;
1401 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001402
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001403 /* Lc: valid range is 0x01 to 0xFF */
1404 if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC) {
1405 p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1406 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001407
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001408 p_t4t->ndef_length = nlen;
1409 p_t4t->state = RW_T4T_STATE_IDLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001410
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001411 if (rw_cb.p_cback) {
1412 rw_data.ndef.status = NFC_STATUS_OK;
1413 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
1414 rw_data.ndef.max_size =
1415 (uint32_t)(p_t4t->cc_file.ndef_fc.max_file_size -
1416 (uint16_t)T4T_FILE_LENGTH_SIZE);
1417 rw_data.ndef.cur_size = nlen;
1418 rw_data.ndef.flags = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
1419 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) {
1420 rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001421 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001422
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001423 (*(rw_cb.p_cback))(RW_T4T_NDEF_DETECT_EVT, &rw_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001424
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001425 DLOG_IF(INFO, nfc_debug_enabled)
1426 << StringPrintf("Sent RW_T4T_NDEF_DETECT_EVT");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001427 }
1428 } else {
1429 /* NLEN should be less than max file size */
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001430 LOG(ERROR) << StringPrintf(
1431 "NLEN (%d) + 2 must be <= max file "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001432 "size (%d)",
1433 nlen, p_t4t->cc_file.ndef_fc.max_file_size);
1434
1435 p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1436 rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001437 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001438 } else {
1439 /* response payload size should be T4T_FILE_LENGTH_SIZE */
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001440 LOG(ERROR) << StringPrintf(
1441 "Length (%d) of R-APDU must be %d", p_r_apdu->len,
1442 T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001443
1444 p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1445 rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
1446 }
1447 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001448
1449 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001450 LOG(ERROR) << StringPrintf("unknown sub_state=%d", p_t4t->sub_state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001451 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1452 break;
1453 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001454}
1455
1456/*******************************************************************************
1457**
1458** Function rw_t4t_sm_read_ndef
1459**
1460** Description State machine for NDEF read procedure
1461**
1462** Returns none
1463**
1464*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001465static void rw_t4t_sm_read_ndef(NFC_HDR* p_r_apdu) {
1466 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1467 uint8_t* p;
1468 uint16_t status_words;
1469 tRW_DATA rw_data;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001470
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001471 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1472 "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
1473 p_t4t->sub_state);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001474
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001475 /* get status words */
1476 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1477 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1478 BE_STREAM_TO_UINT16(status_words, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001479
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001480 if (status_words != T4T_RSP_CMD_CMPLTED) {
1481 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1482 GKI_freebuf(p_r_apdu);
1483 return;
1484 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001485
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001486 switch (p_t4t->sub_state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001487 case RW_T4T_SUBSTATE_WAIT_READ_RESP:
1488
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001489 /* Read partial or complete data */
1490 p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001491
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001492 if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length)) {
1493 p_t4t->rw_length -= p_r_apdu->len;
1494 p_t4t->rw_offset += p_r_apdu->len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001495
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001496 if (rw_cb.p_cback) {
1497 rw_data.data.status = NFC_STATUS_OK;
1498 rw_data.data.p_data = p_r_apdu;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001499
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001500 /* if need to read more data */
1501 if (p_t4t->rw_length > 0) {
1502 (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_EVT, &rw_data);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001503
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001504 if (!rw_t4t_read_file(p_t4t->rw_offset, p_t4t->rw_length, true)) {
1505 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001506 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001507 } else {
1508 p_t4t->state = RW_T4T_STATE_IDLE;
1509
1510 (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
1511
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001512 DLOG_IF(INFO, nfc_debug_enabled)
1513 << StringPrintf("Sent RW_T4T_NDEF_READ_CPLT_EVT");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001514 }
1515
1516 p_r_apdu = NULL;
1517 } else {
1518 p_t4t->rw_length = 0;
1519 p_t4t->state = RW_T4T_STATE_IDLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001520 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001521 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001522 LOG(ERROR) << StringPrintf(
1523 "invalid payload length (%d), rw_length "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001524 "(%d)",
1525 p_r_apdu->len, p_t4t->rw_length);
1526 rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
1527 }
1528 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001529
1530 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001531 LOG(ERROR) << StringPrintf("unknown sub_state = %d", p_t4t->sub_state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001532 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1533 break;
1534 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001535
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001536 if (p_r_apdu) GKI_freebuf(p_r_apdu);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001537}
1538
1539/*******************************************************************************
1540**
1541** Function rw_t4t_sm_update_ndef
1542**
1543** Description State machine for NDEF update procedure
1544**
1545** Returns none
1546**
1547*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001548static void rw_t4t_sm_update_ndef(NFC_HDR* p_r_apdu) {
1549 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1550 uint8_t* p;
1551 uint16_t status_words;
1552 tRW_DATA rw_data;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001553
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001554 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1555 "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
1556 p_t4t->sub_state);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001557
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001558 /* Get status words */
1559 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1560 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1561 BE_STREAM_TO_UINT16(status_words, p);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001562
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001563 if (status_words != T4T_RSP_CMD_CMPLTED) {
1564 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1565 return;
1566 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001567
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001568 switch (p_t4t->sub_state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001569 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
1570
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001571 /* NLEN has been updated */
1572 /* if need to update data */
1573 if (p_t4t->p_update_data) {
1574 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001575
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001576 if (!rw_t4t_update_file()) {
1577 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1578 p_t4t->p_update_data = NULL;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001579 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001580 } else {
1581 p_t4t->state = RW_T4T_STATE_IDLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001582
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001583 /* just finished last step of updating (updating NLEN) */
1584 if (rw_cb.p_cback) {
1585 rw_data.status = NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001586
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001587 (*(rw_cb.p_cback))(RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001588 DLOG_IF(INFO, nfc_debug_enabled)
1589 << StringPrintf("Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001590 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001591 }
1592 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001593
1594 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1595
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001596 /* if updating is not completed */
1597 if (p_t4t->rw_length > 0) {
1598 if (!rw_t4t_update_file()) {
1599 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1600 p_t4t->p_update_data = NULL;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001601 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001602 } else {
1603 p_t4t->p_update_data = NULL;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001604
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001605 /* update NLEN as last step of updating file */
1606 if (!rw_t4t_update_nlen(p_t4t->ndef_length)) {
1607 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1608 } else {
1609 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001610 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001611 }
1612 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001613
1614 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001615 LOG(ERROR) << StringPrintf("unknown sub_state = %d", p_t4t->sub_state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001616 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1617 break;
1618 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001619}
1620
1621/*******************************************************************************
1622**
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001623** Function rw_t4t_sm_set_readonly
1624**
1625** Description State machine for CC update procedure
1626**
1627** Returns none
1628**
1629*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001630static void rw_t4t_sm_set_readonly(NFC_HDR* p_r_apdu) {
1631 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1632 uint8_t* p;
1633 uint16_t status_words;
1634 tRW_DATA rw_data;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001635
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001636 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1637 "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
1638 p_t4t->sub_state);
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001639
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001640 /* Get status words */
1641 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1642 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1643 BE_STREAM_TO_UINT16(status_words, p);
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001644
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001645 if (status_words != T4T_RSP_CMD_CMPLTED) {
1646 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1647 return;
1648 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001649
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001650 switch (p_t4t->sub_state) {
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001651 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1652
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001653 /* CC file has been selected then update write access to read-only in CC
1654 * file */
1655 if (!rw_t4t_update_cc_to_readonly()) {
1656 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1657 } else {
1658 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_CC;
1659 }
1660 break;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001661
1662 case RW_T4T_SUBSTATE_WAIT_UPDATE_CC:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001663 /* CC Updated, Select NDEF File to allow NDEF operation */
1664 p_t4t->cc_file.ndef_fc.write_access = T4T_FC_NO_WRITE_ACCESS;
1665 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001666
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001667 if (!rw_t4t_select_file(p_t4t->cc_file.ndef_fc.file_id)) {
1668 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1669 } else {
1670 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1671 }
1672 break;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001673
1674 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001675 p_t4t->state = RW_T4T_STATE_IDLE;
1676 /* just finished last step of configuring tag read only (Selecting NDEF
1677 * file CC) */
1678 if (rw_cb.p_cback) {
1679 rw_data.status = NFC_STATUS_OK;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001680
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001681 DLOG_IF(INFO, nfc_debug_enabled)
1682 << StringPrintf("Sent RW_T4T_SET_TO_RO_EVT");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001683 (*(rw_cb.p_cback))(RW_T4T_SET_TO_RO_EVT, &rw_data);
1684 }
1685 break;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001686
1687 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001688 LOG(ERROR) << StringPrintf("unknown sub_state = %d", p_t4t->sub_state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001689 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1690 break;
1691 }
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001692}
1693
1694/*******************************************************************************
1695**
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001696** Function rw_t4t_process_timeout
1697**
1698** Description process timeout event
1699**
1700** Returns none
1701**
1702*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001703void rw_t4t_process_timeout(TIMER_LIST_ENT* p_tle) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001704 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("event=%d", p_tle->event);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001705
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001706 if (p_tle->event == NFC_TTYPE_RW_T4T_RESPONSE) {
1707 rw_t4t_handle_error(NFC_STATUS_TIMEOUT, 0, 0);
1708 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001709 LOG(ERROR) << StringPrintf("unknown event=%d", p_tle->event);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001710 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001711}
1712
1713/*******************************************************************************
1714**
Love Khannad09d4bf2017-04-06 14:31:48 +05301715** Function rw_t4t_handle_isodep_nak_rsp
1716**
1717** Description This function handles the response and ntf .
1718**
1719** Returns none
1720**
1721*******************************************************************************/
1722void rw_t4t_handle_isodep_nak_rsp(uint8_t status, bool is_ntf) {
1723 tRW_DATA rw_data;
1724 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001725 DLOG_IF(INFO, nfc_debug_enabled)
1726 << StringPrintf("rw_t4t_handle_isodep_nak_rsp %d", status);
Love Khannad09d4bf2017-04-06 14:31:48 +05301727 if (is_ntf || (status != NFC_STATUS_OK)) {
1728 rw_data.status = status;
1729 nfc_stop_quick_timer(&p_t4t->timer);
1730 p_t4t->state = RW_T4T_STATE_IDLE;
1731 (*(rw_cb.p_cback))(RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1732 }
1733}
1734
1735/*******************************************************************************
1736**
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001737** Function rw_t4t_data_cback
1738**
1739** Description This callback function receives the data from NFCC.
1740**
1741** Returns none
1742**
1743*******************************************************************************/
Ruchi Kandoi9ba6d242017-10-13 16:07:01 -07001744static void rw_t4t_data_cback(__attribute__((unused)) uint8_t conn_id,
1745 tNFC_CONN_EVT event, tNFC_CONN* p_data) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001746 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1747 NFC_HDR* p_r_apdu;
1748 tRW_DATA rw_data;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001749
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001750 uint8_t begin_state = p_t4t->state;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001751
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001752 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("event = 0x%X", event);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001753 nfc_stop_quick_timer(&p_t4t->timer);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001754
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001755 switch (event) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001756 case NFC_DEACTIVATE_CEVT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001757 NFC_SetStaticRfCback(NULL);
1758 p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED;
1759 return;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001760
1761 case NFC_ERROR_CEVT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001762 if (p_t4t->state == RW_T4T_STATE_PRESENCE_CHECK) {
1763 p_t4t->state = RW_T4T_STATE_IDLE;
1764 rw_data.status = NFC_STATUS_FAILED;
1765 (*(rw_cb.p_cback))(RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1766 } else if (p_t4t->state == RW_T4T_STATE_NDEF_FORMAT) {
1767 p_t4t->state = RW_T4T_STATE_IDLE;
1768 rw_data.status = NFC_STATUS_FAILED;
1769 (*(rw_cb.p_cback))(RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
1770 } else if (p_t4t->state != RW_T4T_STATE_IDLE) {
1771 rw_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
1772 rw_t4t_handle_error(rw_data.status, 0, 0);
1773 } else {
1774 p_t4t->state = RW_T4T_STATE_IDLE;
1775 rw_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
1776 (*(rw_cb.p_cback))(RW_T4T_INTF_ERROR_EVT, &rw_data);
1777 }
1778 return;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001779
1780 case NFC_DATA_CEVT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001781 p_r_apdu = (NFC_HDR*)p_data->data.p_data;
1782 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001783
1784 default:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001785 return;
1786 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001787
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001788 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1789 "RW T4T state: <%s (%d)>", rw_t4t_get_state_name(p_t4t->state).c_str(),
1790 p_t4t->state);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001791
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001792 switch (p_t4t->state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001793 case RW_T4T_STATE_IDLE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001794/* Unexpected R-APDU, it should be raw frame response */
1795/* forward to upper layer without parsing */
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001796DLOG_IF(INFO, nfc_debug_enabled)
1797 << StringPrintf("RW T4T Raw Frame: Len [0x%X] Status [%s]", p_r_apdu->len,
1798 NFC_GetStatusName(p_data->data.status).c_str());
1799if (rw_cb.p_cback) {
1800 rw_data.raw_frame.status = p_data->data.status;
1801 rw_data.raw_frame.p_data = p_r_apdu;
1802 (*(rw_cb.p_cback))(RW_T4T_RAW_FRAME_EVT, &rw_data);
1803 p_r_apdu = NULL;
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001804 } else {
1805 GKI_freebuf(p_r_apdu);
1806 }
1807 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001808 case RW_T4T_STATE_DETECT_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001809 rw_t4t_sm_detect_ndef(p_r_apdu);
1810 GKI_freebuf(p_r_apdu);
1811 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001812 case RW_T4T_STATE_READ_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001813 rw_t4t_sm_read_ndef(p_r_apdu);
1814 /* p_r_apdu may send upper lyaer */
1815 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001816 case RW_T4T_STATE_UPDATE_NDEF:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001817 rw_t4t_sm_update_ndef(p_r_apdu);
1818 GKI_freebuf(p_r_apdu);
1819 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001820 case RW_T4T_STATE_PRESENCE_CHECK:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001821 /* if any response, send presence check with ok */
1822 rw_data.status = NFC_STATUS_OK;
1823 p_t4t->state = RW_T4T_STATE_IDLE;
1824 (*(rw_cb.p_cback))(RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1825 GKI_freebuf(p_r_apdu);
1826 break;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07001827 case RW_T4T_STATE_SET_READ_ONLY:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001828 rw_t4t_sm_set_readonly(p_r_apdu);
1829 GKI_freebuf(p_r_apdu);
1830 break;
Jizhou Liao94f37742015-06-03 12:31:03 -07001831 case RW_T4T_STATE_NDEF_FORMAT:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001832 rw_t4t_sm_ndef_format(p_r_apdu);
1833 GKI_freebuf(p_r_apdu);
1834 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001835 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001836 LOG(ERROR) << StringPrintf("invalid state=%d", p_t4t->state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001837 GKI_freebuf(p_r_apdu);
1838 break;
1839 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001840
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001841 if (begin_state != p_t4t->state) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001842 DLOG_IF(INFO, nfc_debug_enabled)
1843 << StringPrintf("RW T4T state changed:<%s> -> <%s>",
1844 rw_t4t_get_state_name(begin_state).c_str(),
1845 rw_t4t_get_state_name(p_t4t->state).c_str());
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001846 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001847}
1848
Jizhou Liao94f37742015-06-03 12:31:03 -07001849/*******************************************************************************
1850**
1851** Function RW_T4tFormatNDef
1852**
1853** Description format T4T tag
1854**
1855** Returns NFC_STATUS_OK if success
1856**
1857*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001858tNFC_STATUS RW_T4tFormatNDef(void) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001859 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
Jizhou Liao94f37742015-06-03 12:31:03 -07001860
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001861 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001862 LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
1863 rw_cb.tcb.t4t.state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001864 return NFC_STATUS_FAILED;
1865 }
Jizhou Liao94f37742015-06-03 12:31:03 -07001866
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001867 rw_cb.tcb.t4t.card_type = 0x00;
Jizhou Liao94f37742015-06-03 12:31:03 -07001868
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001869 if (!rw_t4t_get_hw_version()) {
1870 return NFC_STATUS_FAILED;
1871 }
Jizhou Liao94f37742015-06-03 12:31:03 -07001872
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001873 rw_cb.tcb.t4t.state = RW_T4T_STATE_NDEF_FORMAT;
1874 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION;
Jizhou Liao94f37742015-06-03 12:31:03 -07001875
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001876 return NFC_STATUS_OK;
Jizhou Liao94f37742015-06-03 12:31:03 -07001877}
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001878
1879/*******************************************************************************
1880**
1881** Function rw_t4t_select
1882**
1883** Description Initialise T4T
1884**
1885** Returns NFC_STATUS_OK if success
1886**
1887*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001888tNFC_STATUS rw_t4t_select(void) {
1889 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001890
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001891 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001892
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001893 NFC_SetStaticRfCback(rw_t4t_data_cback);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001894
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001895 p_t4t->state = RW_T4T_STATE_IDLE;
1896 p_t4t->version = T4T_MY_VERSION;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001897
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001898 /* set it min of max R-APDU data size before reading CC file */
1899 p_t4t->cc_file.max_le = T4T_MIN_MLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001900
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001901 /* These will be udated during NDEF detection */
1902 p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
1903 p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001904
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001905 return NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001906}
1907
1908/*******************************************************************************
1909**
1910** Function RW_T4tDetectNDef
1911**
1912** Description This function performs NDEF detection procedure
1913**
1914** RW_T4T_NDEF_DETECT_EVT will be returned
1915**
1916** Returns NFC_STATUS_OK if success
1917** NFC_STATUS_FAILED if T4T is busy or other error
1918**
1919*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001920tNFC_STATUS RW_T4tDetectNDef(void) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001921 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001922
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001923 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001924 LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
1925 rw_cb.tcb.t4t.state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001926 return NFC_STATUS_FAILED;
1927 }
1928
1929 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
1930 /* NDEF Tag application has been selected then select CC file */
1931 if (!rw_t4t_select_file(T4T_CC_FILE_ID)) {
1932 return NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001933 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001934 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1935 } else {
1936 /* Select NDEF Tag Application */
1937 if (!rw_t4t_select_application(rw_cb.tcb.t4t.version)) {
1938 return NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001939 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001940 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1941 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001942
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001943 rw_cb.tcb.t4t.state = RW_T4T_STATE_DETECT_NDEF;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001944
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001945 return NFC_STATUS_OK;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001946}
1947
1948/*******************************************************************************
1949**
1950** Function RW_T4tReadNDef
1951**
1952** Description This function performs NDEF read procedure
1953** Note: RW_T4tDetectNDef () must be called before using this
1954**
1955** The following event will be returned
1956** RW_T4T_NDEF_READ_EVT for each segmented NDEF message
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001957** RW_T4T_NDEF_READ_CPLT_EVT for the last segment or
1958** complete NDEF
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001959** RW_T4T_NDEF_READ_FAIL_EVT for failure
1960**
1961** Returns NFC_STATUS_OK if success
1962** NFC_STATUS_FAILED if T4T is busy or other error
1963**
1964*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001965tNFC_STATUS RW_T4tReadNDef(void) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001966 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001967
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001968 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001969 LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
1970 rw_cb.tcb.t4t.state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001971 return NFC_STATUS_FAILED;
1972 }
1973
1974 /* if NDEF has been detected */
1975 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
1976 /* start reading NDEF */
1977 if (!rw_t4t_read_file(T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length,
1978 false)) {
1979 return NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001980 }
1981
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001982 rw_cb.tcb.t4t.state = RW_T4T_STATE_READ_NDEF;
1983 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001984
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001985 return NFC_STATUS_OK;
1986 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07001987 LOG(ERROR) << StringPrintf("No NDEF detected");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08001988 return NFC_STATUS_FAILED;
1989 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001990}
1991
1992/*******************************************************************************
1993**
1994** Function RW_T4tUpdateNDef
1995**
1996** Description This function performs NDEF update procedure
1997** Note: RW_T4tDetectNDef () must be called before using this
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08001998** Updating data must not be removed until returning
1999** event
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002000**
2001** The following event will be returned
2002** RW_T4T_NDEF_UPDATE_CPLT_EVT for complete
2003** RW_T4T_NDEF_UPDATE_FAIL_EVT for failure
2004**
2005** Returns NFC_STATUS_OK if success
2006** NFC_STATUS_FAILED if T4T is busy or other error
2007**
2008*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002009tNFC_STATUS RW_T4tUpdateNDef(uint16_t length, uint8_t* p_data) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002010 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("length:%d", length);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002011
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002012 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002013 LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
2014 rw_cb.tcb.t4t.state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002015 return NFC_STATUS_FAILED;
2016 }
2017
2018 /* if NDEF has been detected */
2019 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
2020 /* if read-only */
2021 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002022 LOG(ERROR) << StringPrintf("NDEF is read-only");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002023 return NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002024 }
2025
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002026 if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size <
2027 length + T4T_FILE_LENGTH_SIZE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002028 LOG(ERROR) << StringPrintf(
2029 "data (%d bytes) plus NLEN is more than max file "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002030 "size (%d)",
2031 length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
2032 return NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002033 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002034
2035 /* store NDEF length and data */
2036 rw_cb.tcb.t4t.ndef_length = length;
2037 rw_cb.tcb.t4t.p_update_data = p_data;
2038
2039 rw_cb.tcb.t4t.rw_offset = T4T_FILE_LENGTH_SIZE;
2040 rw_cb.tcb.t4t.rw_length = length;
2041
2042 /* set NLEN to 0x0000 for the first step */
2043 if (!rw_t4t_update_nlen(0x0000)) {
2044 return NFC_STATUS_FAILED;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002045 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002046
2047 rw_cb.tcb.t4t.state = RW_T4T_STATE_UPDATE_NDEF;
2048 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
2049
2050 return NFC_STATUS_OK;
2051 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002052 LOG(ERROR) << StringPrintf("No NDEF detected");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002053 return NFC_STATUS_FAILED;
2054 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002055}
2056
2057/*****************************************************************************
2058**
2059** Function RW_T4tPresenceCheck
2060**
2061** Description
2062** Check if the tag is still in the field.
2063**
2064** The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
2065** or non-presence.
Ruchi Kandoi552f2b72017-01-28 16:22:55 -08002066**
2067** option is RW_T4T_CHK_EMPTY_I_BLOCK, use empty I block for presence check
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002068**
2069** Returns
2070** NFC_STATUS_OK, if raw data frame sent
2071** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2072** NFC_STATUS_FAILED: other error
2073**
2074*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002075tNFC_STATUS RW_T4tPresenceCheck(uint8_t option) {
2076 tNFC_STATUS retval = NFC_STATUS_OK;
2077 tRW_DATA evt_data;
2078 bool status;
2079 NFC_HDR* p_data;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002080
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002081 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%d", option);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002082
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002083 /* If RW_SelectTagType was not called (no conn_callback) return failure */
2084 if (!rw_cb.p_cback) {
2085 retval = NFC_STATUS_FAILED;
2086 }
2087 /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with
2088 NFC_STATUS_FAILED */
2089 else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED) {
2090 evt_data.status = NFC_STATUS_FAILED;
2091 (*rw_cb.p_cback)(RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
2092 }
2093 /* If command is pending, assume tag is still present */
2094 else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
2095 evt_data.status = NFC_STATUS_OK;
2096 (*rw_cb.p_cback)(RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
2097 } else {
2098 status = false;
2099 if (option == RW_T4T_CHK_EMPTY_I_BLOCK) {
2100 /* use empty I block for presence check */
Ruchi Kandoi0c515ae2017-01-30 17:48:41 -08002101 p_data = (NFC_HDR*)GKI_getbuf(NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE);
2102 if (p_data != NULL) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002103 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
2104 p_data->len = 0;
2105 if (NFC_SendData(NFC_RF_CONN_ID, (NFC_HDR*)p_data) == NFC_STATUS_OK)
2106 status = true;
2107 }
Love Khannad09d4bf2017-04-06 14:31:48 +05302108 } else if (option == RW_T4T_CHK_ISO_DEP_NAK_PRES_CHK) {
2109 if (NFC_ISODEPNakPresCheck() == NFC_STATUS_OK) status = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002110 }
2111
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002112 if (status == true) {
2113 rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK;
2114 } else {
2115 retval = NFC_STATUS_NO_BUFFERS;
2116 }
2117 }
2118
2119 return (retval);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002120}
2121
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002122/*****************************************************************************
2123**
2124** Function RW_T4tSetNDefReadOnly
2125**
2126** Description This function performs NDEF read-only procedure
2127** Note: RW_T4tDetectNDef() must be called before using this
2128**
2129** The RW_T4T_SET_TO_RO_EVT event will be returned.
2130**
2131** Returns NFC_STATUS_OK if success
2132** NFC_STATUS_FAILED if T4T is busy or other error
2133**
2134*****************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002135tNFC_STATUS RW_T4tSetNDefReadOnly(void) {
2136 tNFC_STATUS retval = NFC_STATUS_OK;
2137 tRW_DATA evt_data;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002138
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002139 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002140
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002141 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002142 LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
2143 rw_cb.tcb.t4t.state);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002144 return NFC_STATUS_FAILED;
2145 }
2146
2147 /* if NDEF has been detected */
2148 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
2149 /* if read-only */
2150 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002151 DLOG_IF(INFO, nfc_debug_enabled)
2152 << StringPrintf("NDEF is already read-only");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002153
2154 evt_data.status = NFC_STATUS_OK;
2155 (*rw_cb.p_cback)(RW_T4T_SET_TO_RO_EVT, &evt_data);
2156 return (retval);
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002157 }
2158
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002159 /* NDEF Tag application has been selected then select CC file */
2160 if (!rw_t4t_select_file(T4T_CC_FILE_ID)) {
2161 return NFC_STATUS_FAILED;
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002162 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002163
2164 rw_cb.tcb.t4t.state = RW_T4T_STATE_SET_READ_ONLY;
2165 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
2166
2167 return NFC_STATUS_OK;
2168 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -07002169 LOG(ERROR) << StringPrintf("No NDEF detected");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002170 return NFC_STATUS_FAILED;
2171 }
2172 return (retval);
Martijn Coenen5c65c3a2013-03-27 13:23:36 -07002173}
2174
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002175/*******************************************************************************
2176**
2177** Function rw_t4t_get_state_name
2178**
2179** Description This function returns the state name.
2180**
2181** NOTE conditionally compiled to save memory.
2182**
2183** Returns pointer to the name
2184**
2185*******************************************************************************/
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002186static std::string rw_t4t_get_state_name(uint8_t state) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002187 switch (state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002188 case RW_T4T_STATE_NOT_ACTIVATED:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002189 return "NOT_ACTIVATED";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002190 case RW_T4T_STATE_IDLE:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002191 return "IDLE";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002192 case RW_T4T_STATE_DETECT_NDEF:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002193 return "NDEF_DETECTION";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002194 case RW_T4T_STATE_READ_NDEF:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002195 return "READ_NDEF";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002196 case RW_T4T_STATE_UPDATE_NDEF:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002197 return "UPDATE_NDEF";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002198 case RW_T4T_STATE_PRESENCE_CHECK:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002199 return "PRESENCE_CHECK";
Evan Chu7c69b272013-05-14 12:48:36 -04002200 case RW_T4T_STATE_SET_READ_ONLY:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002201 return "SET_READ_ONLY";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002202 default:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002203 return "???? UNKNOWN STATE";
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002204 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002205}
2206
2207/*******************************************************************************
2208**
2209** Function rw_t4t_get_sub_state_name
2210**
2211** Description This function returns the sub_state name.
2212**
2213** NOTE conditionally compiled to save memory.
2214**
2215** Returns pointer to the name
2216**
2217*******************************************************************************/
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002218static std::string rw_t4t_get_sub_state_name(uint8_t sub_state) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002219 switch (sub_state) {
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002220 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002221 return "WAIT_SELECT_APP";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002222 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002223 return "WAIT_SELECT_CC";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002224 case RW_T4T_SUBSTATE_WAIT_CC_FILE:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002225 return "WAIT_CC_FILE";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002226 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002227 return "WAIT_SELECT_NDEF_FILE";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002228 case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002229 return "WAIT_READ_NLEN";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002230 case RW_T4T_SUBSTATE_WAIT_READ_RESP:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002231 return "WAIT_READ_RESP";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002232 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002233 return "WAIT_UPDATE_RESP";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002234 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002235 return "WAIT_UPDATE_NLEN";
Jizhou Liao94f37742015-06-03 12:31:03 -07002236 case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002237 return "WAIT_GET_HW_VERSION";
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002238 case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002239 return "WAIT_GET_SW_VERSION";
Jizhou Liao94f37742015-06-03 12:31:03 -07002240 case RW_T4T_SUBSTATE_WAIT_GET_UID:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002241 return "WAIT_GET_UID";
Jizhou Liao94f37742015-06-03 12:31:03 -07002242 case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002243 return "WAIT_CREATE_APP";
Jizhou Liao94f37742015-06-03 12:31:03 -07002244 case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002245 return "WAIT_CREATE_CC";
Jizhou Liao94f37742015-06-03 12:31:03 -07002246 case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002247 return "WAIT_CREATE_NDEF";
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002248 case RW_T4T_SUBSTATE_WAIT_WRITE_CC:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002249 return "WAIT_WRITE_CC";
Jizhou Liao94f37742015-06-03 12:31:03 -07002250 case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002251 return "WAIT_WRITE_NDEF";
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002252 default:
Ruchi Kandoi7dab0e52017-08-03 13:09:49 -07002253 return "???? UNKNOWN SUBSTATE";
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -08002254 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08002255}