1/* 2 * NCI based Driver for STMicroelectronics NFC Chip 3 * 4 * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include <linux/module.h> 20#include <linux/nfc.h> 21#include <linux/delay.h> 22#include <net/nfc/nci.h> 23#include <net/nfc/nci_core.h> 24 25#include "st21nfcb.h" 26#include "st21nfcb_se.h" 27 28struct st21nfcb_pipe_info { 29 u8 pipe_state; 30 u8 src_host_id; 31 u8 src_gate_id; 32 u8 dst_host_id; 33 u8 dst_gate_id; 34} __packed; 35 36/* Hosts */ 37#define ST21NFCB_HOST_CONTROLLER_ID 0x00 38#define ST21NFCB_TERMINAL_HOST_ID 0x01 39#define ST21NFCB_UICC_HOST_ID 0x02 40#define ST21NFCB_ESE_HOST_ID 0xc0 41 42/* Gates */ 43#define ST21NFCB_DEVICE_MGNT_GATE 0x01 44#define ST21NFCB_APDU_READER_GATE 0xf0 45#define ST21NFCB_CONNECTIVITY_GATE 0x41 46 47/* Pipes */ 48#define ST21NFCB_DEVICE_MGNT_PIPE 0x02 49 50/* Connectivity pipe only */ 51#define ST21NFCB_SE_COUNT_PIPE_UICC 0x01 52/* Connectivity + APDU Reader pipe */ 53#define ST21NFCB_SE_COUNT_PIPE_EMBEDDED 0x02 54 55#define ST21NFCB_SE_TO_HOT_PLUG 1000 /* msecs */ 56#define ST21NFCB_SE_TO_PIPES 2000 57 58#define ST21NFCB_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80) 59 60#define NCI_HCI_APDU_PARAM_ATR 0x01 61#define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01 62#define NCI_HCI_ADMIN_PARAM_WHITELIST 0x03 63#define NCI_HCI_ADMIN_PARAM_HOST_LIST 0x04 64 65#define ST21NFCB_EVT_SE_HARD_RESET 0x20 66#define ST21NFCB_EVT_TRANSMIT_DATA 0x10 67#define ST21NFCB_EVT_WTX_REQUEST 0x11 68#define ST21NFCB_EVT_SE_SOFT_RESET 0x11 69#define ST21NFCB_EVT_SE_END_OF_APDU_TRANSFER 0x21 70#define ST21NFCB_EVT_HOT_PLUG 0x03 71 72#define ST21NFCB_SE_MODE_OFF 0x00 73#define ST21NFCB_SE_MODE_ON 0x01 74 75#define ST21NFCB_EVT_CONNECTIVITY 0x10 76#define ST21NFCB_EVT_TRANSACTION 0x12 77 78#define ST21NFCB_DM_GETINFO 0x13 79#define ST21NFCB_DM_GETINFO_PIPE_LIST 0x02 80#define ST21NFCB_DM_GETINFO_PIPE_INFO 0x01 81#define ST21NFCB_DM_PIPE_CREATED 0x02 82#define ST21NFCB_DM_PIPE_OPEN 0x04 83#define ST21NFCB_DM_RF_ACTIVE 0x80 84#define ST21NFCB_DM_DISCONNECT 0x30 85 86#define ST21NFCB_DM_IS_PIPE_OPEN(p) \ 87 ((p & 0x0f) == (ST21NFCB_DM_PIPE_CREATED | ST21NFCB_DM_PIPE_OPEN)) 88 89#define ST21NFCB_ATR_DEFAULT_BWI 0x04 90 91/* 92 * WT = 2^BWI/10[s], convert into msecs and add a secure 93 * room by increasing by 2 this timeout 94 */ 95#define ST21NFCB_BWI_TO_TIMEOUT(x) ((1 << x) * 200) 96#define ST21NFCB_ATR_GET_Y_FROM_TD(x) (x >> 4) 97 98/* If TA is present bit 0 is set */ 99#define ST21NFCB_ATR_TA_PRESENT(x) (x & 0x01) 100/* If TB is present bit 1 is set */ 101#define ST21NFCB_ATR_TB_PRESENT(x) (x & 0x02) 102 103#define ST21NFCB_NUM_DEVICES 256 104 105static DECLARE_BITMAP(dev_mask, ST21NFCB_NUM_DEVICES); 106 107/* Here are the mandatory pipe for st21nfcb */ 108static struct nci_hci_gate st21nfcb_gates[] = { 109 {NCI_HCI_ADMIN_GATE, NCI_HCI_ADMIN_PIPE, 110 ST21NFCB_HOST_CONTROLLER_ID}, 111 {NCI_HCI_LINK_MGMT_GATE, NCI_HCI_LINK_MGMT_PIPE, 112 ST21NFCB_HOST_CONTROLLER_ID}, 113 {ST21NFCB_DEVICE_MGNT_GATE, ST21NFCB_DEVICE_MGNT_PIPE, 114 ST21NFCB_HOST_CONTROLLER_ID}, 115 116 /* Secure element pipes are created by secure element host */ 117 {ST21NFCB_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE, 118 ST21NFCB_HOST_CONTROLLER_ID}, 119 {ST21NFCB_APDU_READER_GATE, NCI_HCI_DO_NOT_OPEN_PIPE, 120 ST21NFCB_HOST_CONTROLLER_ID}, 121}; 122 123static u8 st21nfcb_se_get_bwi(struct nci_dev *ndev) 124{ 125 int i; 126 u8 td; 127 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 128 129 /* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */ 130 for (i = 1; i < ST21NFCB_ESE_MAX_LENGTH; i++) { 131 td = ST21NFCB_ATR_GET_Y_FROM_TD(info->se_info.atr[i]); 132 if (ST21NFCB_ATR_TA_PRESENT(td)) 133 i++; 134 if (ST21NFCB_ATR_TB_PRESENT(td)) { 135 i++; 136 return info->se_info.atr[i] >> 4; 137 } 138 } 139 return ST21NFCB_ATR_DEFAULT_BWI; 140} 141 142static void st21nfcb_se_get_atr(struct nci_dev *ndev) 143{ 144 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 145 int r; 146 struct sk_buff *skb; 147 148 r = nci_hci_get_param(ndev, ST21NFCB_APDU_READER_GATE, 149 NCI_HCI_APDU_PARAM_ATR, &skb); 150 if (r < 0) 151 return; 152 153 if (skb->len <= ST21NFCB_ESE_MAX_LENGTH) { 154 memcpy(info->se_info.atr, skb->data, skb->len); 155 156 info->se_info.wt_timeout = 157 ST21NFCB_BWI_TO_TIMEOUT(st21nfcb_se_get_bwi(ndev)); 158 } 159 kfree_skb(skb); 160} 161 162int st21nfcb_hci_load_session(struct nci_dev *ndev) 163{ 164 int i, j, r; 165 struct sk_buff *skb_pipe_list, *skb_pipe_info; 166 struct st21nfcb_pipe_info *dm_pipe_info; 167 u8 pipe_list[] = { ST21NFCB_DM_GETINFO_PIPE_LIST, 168 ST21NFCB_TERMINAL_HOST_ID}; 169 u8 pipe_info[] = { ST21NFCB_DM_GETINFO_PIPE_INFO, 170 ST21NFCB_TERMINAL_HOST_ID, 0}; 171 172 /* On ST21NFCB device pipes number are dynamics 173 * If pipes are already created, hci_dev_up will fail. 174 * Doing a clear all pipe is a bad idea because: 175 * - It does useless EEPROM cycling 176 * - It might cause issue for secure elements support 177 * (such as removing connectivity or APDU reader pipe) 178 * A better approach on ST21NFCB is to: 179 * - get a pipe list for each host. 180 * (eg: ST21NFCB_HOST_CONTROLLER_ID for now). 181 * (TODO Later on UICC HOST and eSE HOST) 182 * - get pipe information 183 * - match retrieved pipe list in st21nfcb_gates 184 * ST21NFCB_DEVICE_MGNT_GATE is a proprietary gate 185 * with ST21NFCB_DEVICE_MGNT_PIPE. 186 * Pipe can be closed and need to be open. 187 */ 188 r = nci_hci_connect_gate(ndev, ST21NFCB_HOST_CONTROLLER_ID, 189 ST21NFCB_DEVICE_MGNT_GATE, 190 ST21NFCB_DEVICE_MGNT_PIPE); 191 if (r < 0) 192 goto free_info; 193 194 /* Get pipe list */ 195 r = nci_hci_send_cmd(ndev, ST21NFCB_DEVICE_MGNT_GATE, 196 ST21NFCB_DM_GETINFO, pipe_list, sizeof(pipe_list), 197 &skb_pipe_list); 198 if (r < 0) 199 goto free_info; 200 201 /* Complete the existing gate_pipe table */ 202 for (i = 0; i < skb_pipe_list->len; i++) { 203 pipe_info[2] = skb_pipe_list->data[i]; 204 r = nci_hci_send_cmd(ndev, ST21NFCB_DEVICE_MGNT_GATE, 205 ST21NFCB_DM_GETINFO, pipe_info, 206 sizeof(pipe_info), &skb_pipe_info); 207 208 if (r) 209 continue; 210 211 /* 212 * Match pipe ID and gate ID 213 * Output format from ST21NFC_DM_GETINFO is: 214 * - pipe state (1byte) 215 * - source hid (1byte) 216 * - source gid (1byte) 217 * - destination hid (1byte) 218 * - destination gid (1byte) 219 */ 220 dm_pipe_info = (struct st21nfcb_pipe_info *)skb_pipe_info->data; 221 if (dm_pipe_info->dst_gate_id == ST21NFCB_APDU_READER_GATE && 222 dm_pipe_info->src_host_id != ST21NFCB_ESE_HOST_ID) { 223 pr_err("Unexpected apdu_reader pipe on host %x\n", 224 dm_pipe_info->src_host_id); 225 continue; 226 } 227 228 for (j = 0; (j < ARRAY_SIZE(st21nfcb_gates)) && 229 (st21nfcb_gates[j].gate != dm_pipe_info->dst_gate_id); j++) 230 ; 231 232 if (j < ARRAY_SIZE(st21nfcb_gates) && 233 st21nfcb_gates[j].gate == dm_pipe_info->dst_gate_id && 234 ST21NFCB_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) { 235 st21nfcb_gates[j].pipe = pipe_info[2]; 236 237 ndev->hci_dev->gate2pipe[st21nfcb_gates[j].gate] = 238 st21nfcb_gates[j].pipe; 239 ndev->hci_dev->pipes[st21nfcb_gates[j].pipe].gate = 240 st21nfcb_gates[j].gate; 241 ndev->hci_dev->pipes[st21nfcb_gates[j].pipe].host = 242 dm_pipe_info->src_host_id; 243 } 244 } 245 246 memcpy(ndev->hci_dev->init_data.gates, st21nfcb_gates, 247 sizeof(st21nfcb_gates)); 248 249free_info: 250 kfree_skb(skb_pipe_info); 251 kfree_skb(skb_pipe_list); 252 return r; 253} 254EXPORT_SYMBOL_GPL(st21nfcb_hci_load_session); 255 256static void st21nfcb_hci_admin_event_received(struct nci_dev *ndev, 257 u8 event, struct sk_buff *skb) 258{ 259 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 260 261 switch (event) { 262 case ST21NFCB_EVT_HOT_PLUG: 263 if (info->se_info.se_active) { 264 if (!ST21NFCB_EVT_HOT_PLUG_IS_INHIBITED(skb)) { 265 del_timer_sync(&info->se_info.se_active_timer); 266 info->se_info.se_active = false; 267 complete(&info->se_info.req_completion); 268 } else { 269 mod_timer(&info->se_info.se_active_timer, 270 jiffies + 271 msecs_to_jiffies(ST21NFCB_SE_TO_PIPES)); 272 } 273 } 274 break; 275 } 276} 277 278static int st21nfcb_hci_apdu_reader_event_received(struct nci_dev *ndev, 279 u8 event, 280 struct sk_buff *skb) 281{ 282 int r = 0; 283 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 284 285 pr_debug("apdu reader gate event: %x\n", event); 286 287 switch (event) { 288 case ST21NFCB_EVT_TRANSMIT_DATA: 289 del_timer_sync(&info->se_info.bwi_timer); 290 info->se_info.bwi_active = false; 291 info->se_info.cb(info->se_info.cb_context, 292 skb->data, skb->len, 0); 293 break; 294 case ST21NFCB_EVT_WTX_REQUEST: 295 mod_timer(&info->se_info.bwi_timer, jiffies + 296 msecs_to_jiffies(info->se_info.wt_timeout)); 297 break; 298 } 299 300 kfree_skb(skb); 301 return r; 302} 303 304/* 305 * Returns: 306 * <= 0: driver handled the event, skb consumed 307 * 1: driver does not handle the event, please do standard processing 308 */ 309static int st21nfcb_hci_connectivity_event_received(struct nci_dev *ndev, 310 u8 host, u8 event, 311 struct sk_buff *skb) 312{ 313 int r = 0; 314 struct device *dev = &ndev->nfc_dev->dev; 315 struct nfc_evt_transaction *transaction; 316 317 pr_debug("connectivity gate event: %x\n", event); 318 319 switch (event) { 320 case ST21NFCB_EVT_CONNECTIVITY: 321 322 break; 323 case ST21NFCB_EVT_TRANSACTION: 324 /* According to specification etsi 102 622 325 * 11.2.2.4 EVT_TRANSACTION Table 52 326 * Description Tag Length 327 * AID 81 5 to 16 328 * PARAMETERS 82 0 to 255 329 */ 330 if (skb->len < NFC_MIN_AID_LENGTH + 2 && 331 skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) 332 return -EPROTO; 333 334 transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev, 335 skb->len - 2, GFP_KERNEL); 336 337 transaction->aid_len = skb->data[1]; 338 memcpy(transaction->aid, &skb->data[2], transaction->aid_len); 339 340 /* Check next byte is PARAMETERS tag (82) */ 341 if (skb->data[transaction->aid_len + 2] != 342 NFC_EVT_TRANSACTION_PARAMS_TAG) 343 return -EPROTO; 344 345 transaction->params_len = skb->data[transaction->aid_len + 3]; 346 memcpy(transaction->params, skb->data + 347 transaction->aid_len + 4, transaction->params_len); 348 349 r = nfc_se_transaction(ndev->nfc_dev, host, transaction); 350 break; 351 default: 352 return 1; 353 } 354 kfree_skb(skb); 355 return r; 356} 357 358void st21nfcb_hci_event_received(struct nci_dev *ndev, u8 pipe, 359 u8 event, struct sk_buff *skb) 360{ 361 u8 gate = ndev->hci_dev->pipes[pipe].gate; 362 u8 host = ndev->hci_dev->pipes[pipe].host; 363 364 switch (gate) { 365 case NCI_HCI_ADMIN_GATE: 366 st21nfcb_hci_admin_event_received(ndev, event, skb); 367 break; 368 case ST21NFCB_APDU_READER_GATE: 369 st21nfcb_hci_apdu_reader_event_received(ndev, event, skb); 370 break; 371 case ST21NFCB_CONNECTIVITY_GATE: 372 st21nfcb_hci_connectivity_event_received(ndev, host, event, 373 skb); 374 break; 375 } 376} 377EXPORT_SYMBOL_GPL(st21nfcb_hci_event_received); 378 379 380void st21nfcb_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd, 381 struct sk_buff *skb) 382{ 383 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 384 u8 gate = ndev->hci_dev->pipes[pipe].gate; 385 386 pr_debug("cmd: %x\n", cmd); 387 388 switch (cmd) { 389 case NCI_HCI_ANY_OPEN_PIPE: 390 if (gate != ST21NFCB_APDU_READER_GATE && 391 ndev->hci_dev->pipes[pipe].host != ST21NFCB_UICC_HOST_ID) 392 ndev->hci_dev->count_pipes++; 393 394 if (ndev->hci_dev->count_pipes == 395 ndev->hci_dev->expected_pipes) { 396 del_timer_sync(&info->se_info.se_active_timer); 397 info->se_info.se_active = false; 398 ndev->hci_dev->count_pipes = 0; 399 complete(&info->se_info.req_completion); 400 } 401 break; 402 } 403} 404EXPORT_SYMBOL_GPL(st21nfcb_hci_cmd_received); 405 406/* 407 * Remarks: On some early st21nfcb firmware, nci_nfcee_mode_set(0) 408 * is rejected 409 */ 410static int st21nfcb_nci_control_se(struct nci_dev *ndev, u8 se_idx, 411 u8 state) 412{ 413 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 414 int r; 415 struct sk_buff *sk_host_list; 416 u8 host_id; 417 418 switch (se_idx) { 419 case ST21NFCB_UICC_HOST_ID: 420 ndev->hci_dev->count_pipes = 0; 421 ndev->hci_dev->expected_pipes = ST21NFCB_SE_COUNT_PIPE_UICC; 422 break; 423 case ST21NFCB_ESE_HOST_ID: 424 ndev->hci_dev->count_pipes = 0; 425 ndev->hci_dev->expected_pipes = ST21NFCB_SE_COUNT_PIPE_EMBEDDED; 426 break; 427 default: 428 return -EINVAL; 429 } 430 431 /* 432 * Wait for an EVT_HOT_PLUG in order to 433 * retrieve a relevant host list. 434 */ 435 reinit_completion(&info->se_info.req_completion); 436 r = nci_nfcee_mode_set(ndev, se_idx, NCI_NFCEE_ENABLE); 437 if (r != NCI_STATUS_OK) 438 return r; 439 440 mod_timer(&info->se_info.se_active_timer, jiffies + 441 msecs_to_jiffies(ST21NFCB_SE_TO_HOT_PLUG)); 442 info->se_info.se_active = true; 443 444 /* Ignore return value and check in any case the host_list */ 445 wait_for_completion_interruptible(&info->se_info.req_completion); 446 447 /* There might be some "collision" after receiving a HOT_PLUG event 448 * This may cause the CLF to not answer to the next hci command. 449 * There is no possible synchronization to prevent this. 450 * Adding a small delay is the only way to solve the issue. 451 */ 452 usleep_range(3000, 5000); 453 454 r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE, 455 NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list); 456 if (r != NCI_HCI_ANY_OK) 457 return r; 458 459 host_id = sk_host_list->data[sk_host_list->len - 1]; 460 kfree_skb(sk_host_list); 461 if (state == ST21NFCB_SE_MODE_ON && host_id == se_idx) 462 return se_idx; 463 else if (state == ST21NFCB_SE_MODE_OFF && host_id != se_idx) 464 return se_idx; 465 466 return -1; 467} 468 469int st21nfcb_nci_disable_se(struct nci_dev *ndev, u32 se_idx) 470{ 471 int r; 472 473 pr_debug("st21nfcb_nci_disable_se\n"); 474 475 if (se_idx == NFC_SE_EMBEDDED) { 476 r = nci_hci_send_event(ndev, ST21NFCB_APDU_READER_GATE, 477 ST21NFCB_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0); 478 if (r < 0) 479 return r; 480 } 481 482 return 0; 483} 484EXPORT_SYMBOL_GPL(st21nfcb_nci_disable_se); 485 486int st21nfcb_nci_enable_se(struct nci_dev *ndev, u32 se_idx) 487{ 488 int r; 489 490 pr_debug("st21nfcb_nci_enable_se\n"); 491 492 if (se_idx == ST21NFCB_HCI_HOST_ID_ESE) { 493 r = nci_hci_send_event(ndev, ST21NFCB_APDU_READER_GATE, 494 ST21NFCB_EVT_SE_SOFT_RESET, NULL, 0); 495 if (r < 0) 496 return r; 497 } 498 499 return 0; 500} 501EXPORT_SYMBOL_GPL(st21nfcb_nci_enable_se); 502 503static int st21nfcb_hci_network_init(struct nci_dev *ndev) 504{ 505 struct core_conn_create_dest_spec_params *dest_params; 506 struct dest_spec_params spec_params; 507 struct nci_conn_info *conn_info; 508 int r, dev_num; 509 510 dest_params = 511 kzalloc(sizeof(struct core_conn_create_dest_spec_params) + 512 sizeof(struct dest_spec_params), GFP_KERNEL); 513 if (dest_params == NULL) { 514 r = -ENOMEM; 515 goto exit; 516 } 517 518 dest_params->type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE; 519 dest_params->length = sizeof(struct dest_spec_params); 520 spec_params.id = ndev->hci_dev->nfcee_id; 521 spec_params.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS; 522 memcpy(dest_params->value, &spec_params, sizeof(struct dest_spec_params)); 523 r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCEE, 1, 524 sizeof(struct core_conn_create_dest_spec_params) + 525 sizeof(struct dest_spec_params), 526 dest_params); 527 if (r != NCI_STATUS_OK) 528 goto free_dest_params; 529 530 conn_info = ndev->hci_dev->conn_info; 531 if (!conn_info) 532 goto free_dest_params; 533 534 memcpy(ndev->hci_dev->init_data.gates, st21nfcb_gates, 535 sizeof(st21nfcb_gates)); 536 537 /* 538 * Session id must include the driver name + i2c bus addr 539 * persistent info to discriminate 2 identical chips 540 */ 541 dev_num = find_first_zero_bit(dev_mask, ST21NFCB_NUM_DEVICES); 542 if (dev_num >= ST21NFCB_NUM_DEVICES) { 543 r = -ENODEV; 544 goto free_dest_params; 545 } 546 547 scnprintf(ndev->hci_dev->init_data.session_id, 548 sizeof(ndev->hci_dev->init_data.session_id), 549 "%s%2x", "ST21BH", dev_num); 550 551 r = nci_hci_dev_session_init(ndev); 552 if (r != NCI_HCI_ANY_OK) 553 goto free_dest_params; 554 555 r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id, 556 NCI_NFCEE_ENABLE); 557 if (r != NCI_STATUS_OK) 558 goto free_dest_params; 559 560free_dest_params: 561 kfree(dest_params); 562 563exit: 564 return r; 565} 566 567int st21nfcb_nci_discover_se(struct nci_dev *ndev) 568{ 569 u8 param[2]; 570 int r; 571 int se_count = 0; 572 573 pr_debug("st21nfcb_nci_discover_se\n"); 574 575 r = st21nfcb_hci_network_init(ndev); 576 if (r != 0) 577 return r; 578 579 param[0] = ST21NFCB_UICC_HOST_ID; 580 param[1] = ST21NFCB_HCI_HOST_ID_ESE; 581 r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE, 582 NCI_HCI_ADMIN_PARAM_WHITELIST, 583 param, sizeof(param)); 584 if (r != NCI_HCI_ANY_OK) 585 return r; 586 587 r = st21nfcb_nci_control_se(ndev, ST21NFCB_UICC_HOST_ID, 588 ST21NFCB_SE_MODE_ON); 589 if (r == ST21NFCB_UICC_HOST_ID) { 590 nfc_add_se(ndev->nfc_dev, ST21NFCB_UICC_HOST_ID, NFC_SE_UICC); 591 se_count++; 592 } 593 594 /* Try to enable eSE in order to check availability */ 595 r = st21nfcb_nci_control_se(ndev, ST21NFCB_HCI_HOST_ID_ESE, 596 ST21NFCB_SE_MODE_ON); 597 if (r == ST21NFCB_HCI_HOST_ID_ESE) { 598 nfc_add_se(ndev->nfc_dev, ST21NFCB_HCI_HOST_ID_ESE, 599 NFC_SE_EMBEDDED); 600 se_count++; 601 st21nfcb_se_get_atr(ndev); 602 } 603 604 return !se_count; 605} 606EXPORT_SYMBOL_GPL(st21nfcb_nci_discover_se); 607 608int st21nfcb_nci_se_io(struct nci_dev *ndev, u32 se_idx, 609 u8 *apdu, size_t apdu_length, 610 se_io_cb_t cb, void *cb_context) 611{ 612 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 613 614 pr_debug("\n"); 615 616 switch (se_idx) { 617 case ST21NFCB_HCI_HOST_ID_ESE: 618 info->se_info.cb = cb; 619 info->se_info.cb_context = cb_context; 620 mod_timer(&info->se_info.bwi_timer, jiffies + 621 msecs_to_jiffies(info->se_info.wt_timeout)); 622 info->se_info.bwi_active = true; 623 return nci_hci_send_event(ndev, ST21NFCB_APDU_READER_GATE, 624 ST21NFCB_EVT_TRANSMIT_DATA, apdu, 625 apdu_length); 626 default: 627 return -ENODEV; 628 } 629} 630EXPORT_SYMBOL(st21nfcb_nci_se_io); 631 632static void st21nfcb_se_wt_timeout(unsigned long data) 633{ 634 /* 635 * No answer from the secure element 636 * within the defined timeout. 637 * Let's send a reset request as recovery procedure. 638 * According to the situation, we first try to send a software reset 639 * to the secure element. If the next command is still not 640 * answering in time, we send to the CLF a secure element hardware 641 * reset request. 642 */ 643 /* hardware reset managed through VCC_UICC_OUT power supply */ 644 u8 param = 0x01; 645 struct st21nfcb_nci_info *info = (struct st21nfcb_nci_info *) data; 646 647 pr_debug("\n"); 648 649 info->se_info.bwi_active = false; 650 651 if (!info->se_info.xch_error) { 652 info->se_info.xch_error = true; 653 nci_hci_send_event(info->ndlc->ndev, ST21NFCB_APDU_READER_GATE, 654 ST21NFCB_EVT_SE_SOFT_RESET, NULL, 0); 655 } else { 656 info->se_info.xch_error = false; 657 nci_hci_send_event(info->ndlc->ndev, ST21NFCB_DEVICE_MGNT_GATE, 658 ST21NFCB_EVT_SE_HARD_RESET, ¶m, 1); 659 } 660 info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME); 661} 662 663static void st21nfcb_se_activation_timeout(unsigned long data) 664{ 665 struct st21nfcb_nci_info *info = (struct st21nfcb_nci_info *) data; 666 667 pr_debug("\n"); 668 669 info->se_info.se_active = false; 670 671 complete(&info->se_info.req_completion); 672} 673 674int st21nfcb_se_init(struct nci_dev *ndev) 675{ 676 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 677 678 init_completion(&info->se_info.req_completion); 679 /* initialize timers */ 680 init_timer(&info->se_info.bwi_timer); 681 info->se_info.bwi_timer.data = (unsigned long)info; 682 info->se_info.bwi_timer.function = st21nfcb_se_wt_timeout; 683 info->se_info.bwi_active = false; 684 685 init_timer(&info->se_info.se_active_timer); 686 info->se_info.se_active_timer.data = (unsigned long)info; 687 info->se_info.se_active_timer.function = 688 st21nfcb_se_activation_timeout; 689 info->se_info.se_active = false; 690 691 info->se_info.xch_error = false; 692 693 info->se_info.wt_timeout = 694 ST21NFCB_BWI_TO_TIMEOUT(ST21NFCB_ATR_DEFAULT_BWI); 695 696 return 0; 697} 698EXPORT_SYMBOL(st21nfcb_se_init); 699 700void st21nfcb_se_deinit(struct nci_dev *ndev) 701{ 702 struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); 703 704 if (info->se_info.bwi_active) 705 del_timer_sync(&info->se_info.bwi_timer); 706 if (info->se_info.se_active) 707 del_timer_sync(&info->se_info.se_active_timer); 708 709 info->se_info.se_active = false; 710 info->se_info.bwi_active = false; 711} 712EXPORT_SYMBOL(st21nfcb_se_deinit); 713 714