0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/nfc.h>
0010 #include <linux/delay.h>
0011 #include <net/nfc/nci.h>
0012 #include <net/nfc/nci_core.h>
0013
0014 #include "st-nci.h"
0015
0016 struct st_nci_pipe_info {
0017 u8 pipe_state;
0018 u8 src_host_id;
0019 u8 src_gate_id;
0020 u8 dst_host_id;
0021 u8 dst_gate_id;
0022 } __packed;
0023
0024
0025 #define ST_NCI_HOST_CONTROLLER_ID 0x00
0026 #define ST_NCI_TERMINAL_HOST_ID 0x01
0027 #define ST_NCI_UICC_HOST_ID 0x02
0028 #define ST_NCI_ESE_HOST_ID 0xc0
0029
0030
0031 #define ST_NCI_APDU_READER_GATE 0xf0
0032 #define ST_NCI_CONNECTIVITY_GATE 0x41
0033
0034
0035 #define ST_NCI_DEVICE_MGNT_PIPE 0x02
0036
0037
0038 #define ST_NCI_SE_COUNT_PIPE_UICC 0x01
0039
0040 #define ST_NCI_SE_COUNT_PIPE_EMBEDDED 0x02
0041
0042 #define ST_NCI_SE_TO_HOT_PLUG 1000
0043 #define ST_NCI_SE_TO_PIPES 2000
0044
0045 #define ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
0046
0047 #define NCI_HCI_APDU_PARAM_ATR 0x01
0048 #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01
0049 #define NCI_HCI_ADMIN_PARAM_WHITELIST 0x03
0050 #define NCI_HCI_ADMIN_PARAM_HOST_LIST 0x04
0051
0052 #define ST_NCI_EVT_SE_HARD_RESET 0x20
0053 #define ST_NCI_EVT_TRANSMIT_DATA 0x10
0054 #define ST_NCI_EVT_WTX_REQUEST 0x11
0055 #define ST_NCI_EVT_SE_SOFT_RESET 0x11
0056 #define ST_NCI_EVT_SE_END_OF_APDU_TRANSFER 0x21
0057 #define ST_NCI_EVT_HOT_PLUG 0x03
0058
0059 #define ST_NCI_SE_MODE_OFF 0x00
0060 #define ST_NCI_SE_MODE_ON 0x01
0061
0062 #define ST_NCI_EVT_CONNECTIVITY 0x10
0063 #define ST_NCI_EVT_TRANSACTION 0x12
0064
0065 #define ST_NCI_DM_GETINFO 0x13
0066 #define ST_NCI_DM_GETINFO_PIPE_LIST 0x02
0067 #define ST_NCI_DM_GETINFO_PIPE_INFO 0x01
0068 #define ST_NCI_DM_PIPE_CREATED 0x02
0069 #define ST_NCI_DM_PIPE_OPEN 0x04
0070 #define ST_NCI_DM_RF_ACTIVE 0x80
0071 #define ST_NCI_DM_DISCONNECT 0x30
0072
0073 #define ST_NCI_DM_IS_PIPE_OPEN(p) \
0074 ((p & 0x0f) == (ST_NCI_DM_PIPE_CREATED | ST_NCI_DM_PIPE_OPEN))
0075
0076 #define ST_NCI_ATR_DEFAULT_BWI 0x04
0077
0078
0079
0080
0081
0082 #define ST_NCI_BWI_TO_TIMEOUT(x) ((1 << x) * 200)
0083 #define ST_NCI_ATR_GET_Y_FROM_TD(x) (x >> 4)
0084
0085
0086 #define ST_NCI_ATR_TA_PRESENT(x) (x & 0x01)
0087
0088 #define ST_NCI_ATR_TB_PRESENT(x) (x & 0x02)
0089
0090 #define ST_NCI_NUM_DEVICES 256
0091
0092 static DECLARE_BITMAP(dev_mask, ST_NCI_NUM_DEVICES);
0093
0094
0095 static struct nci_hci_gate st_nci_gates[] = {
0096 {NCI_HCI_ADMIN_GATE, NCI_HCI_ADMIN_PIPE,
0097 ST_NCI_HOST_CONTROLLER_ID},
0098 {NCI_HCI_LINK_MGMT_GATE, NCI_HCI_LINK_MGMT_PIPE,
0099 ST_NCI_HOST_CONTROLLER_ID},
0100 {ST_NCI_DEVICE_MGNT_GATE, ST_NCI_DEVICE_MGNT_PIPE,
0101 ST_NCI_HOST_CONTROLLER_ID},
0102
0103 {NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
0104 ST_NCI_HOST_CONTROLLER_ID},
0105
0106
0107 {ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
0108 ST_NCI_HOST_CONTROLLER_ID},
0109 {ST_NCI_APDU_READER_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
0110 ST_NCI_HOST_CONTROLLER_ID},
0111 };
0112
0113 static u8 st_nci_se_get_bwi(struct nci_dev *ndev)
0114 {
0115 int i;
0116 u8 td;
0117 struct st_nci_info *info = nci_get_drvdata(ndev);
0118
0119
0120 for (i = 1; i < ST_NCI_ESE_MAX_LENGTH; i++) {
0121 td = ST_NCI_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
0122 if (ST_NCI_ATR_TA_PRESENT(td))
0123 i++;
0124 if (ST_NCI_ATR_TB_PRESENT(td)) {
0125 i++;
0126 return info->se_info.atr[i] >> 4;
0127 }
0128 }
0129 return ST_NCI_ATR_DEFAULT_BWI;
0130 }
0131
0132 static void st_nci_se_get_atr(struct nci_dev *ndev)
0133 {
0134 struct st_nci_info *info = nci_get_drvdata(ndev);
0135 int r;
0136 struct sk_buff *skb;
0137
0138 r = nci_hci_get_param(ndev, ST_NCI_APDU_READER_GATE,
0139 NCI_HCI_APDU_PARAM_ATR, &skb);
0140 if (r < 0)
0141 return;
0142
0143 if (skb->len <= ST_NCI_ESE_MAX_LENGTH) {
0144 memcpy(info->se_info.atr, skb->data, skb->len);
0145
0146 info->se_info.wt_timeout =
0147 ST_NCI_BWI_TO_TIMEOUT(st_nci_se_get_bwi(ndev));
0148 }
0149 kfree_skb(skb);
0150 }
0151
0152 int st_nci_hci_load_session(struct nci_dev *ndev)
0153 {
0154 int i, j, r;
0155 struct sk_buff *skb_pipe_list, *skb_pipe_info;
0156 struct st_nci_pipe_info *dm_pipe_info;
0157 u8 pipe_list[] = { ST_NCI_DM_GETINFO_PIPE_LIST,
0158 ST_NCI_TERMINAL_HOST_ID};
0159 u8 pipe_info[] = { ST_NCI_DM_GETINFO_PIPE_INFO,
0160 ST_NCI_TERMINAL_HOST_ID, 0};
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID,
0179 ST_NCI_DEVICE_MGNT_GATE,
0180 ST_NCI_DEVICE_MGNT_PIPE);
0181 if (r < 0)
0182 return r;
0183
0184
0185 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0186 ST_NCI_DM_GETINFO, pipe_list, sizeof(pipe_list),
0187 &skb_pipe_list);
0188 if (r < 0)
0189 return r;
0190
0191
0192 for (i = 0; i < skb_pipe_list->len; i++) {
0193 pipe_info[2] = skb_pipe_list->data[i];
0194 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0195 ST_NCI_DM_GETINFO, pipe_info,
0196 sizeof(pipe_info), &skb_pipe_info);
0197
0198 if (r)
0199 continue;
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 dm_pipe_info = (struct st_nci_pipe_info *)skb_pipe_info->data;
0211 if (dm_pipe_info->dst_gate_id == ST_NCI_APDU_READER_GATE &&
0212 dm_pipe_info->src_host_id == ST_NCI_UICC_HOST_ID) {
0213 pr_err("Unexpected apdu_reader pipe on host %x\n",
0214 dm_pipe_info->src_host_id);
0215 kfree_skb(skb_pipe_info);
0216 continue;
0217 }
0218
0219 for (j = 3; (j < ARRAY_SIZE(st_nci_gates)) &&
0220 (st_nci_gates[j].gate != dm_pipe_info->dst_gate_id); j++)
0221 ;
0222
0223 if (j < ARRAY_SIZE(st_nci_gates) &&
0224 st_nci_gates[j].gate == dm_pipe_info->dst_gate_id &&
0225 ST_NCI_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) {
0226 ndev->hci_dev->init_data.gates[j].pipe = pipe_info[2];
0227
0228 ndev->hci_dev->gate2pipe[st_nci_gates[j].gate] =
0229 pipe_info[2];
0230 ndev->hci_dev->pipes[pipe_info[2]].gate =
0231 st_nci_gates[j].gate;
0232 ndev->hci_dev->pipes[pipe_info[2]].host =
0233 dm_pipe_info->src_host_id;
0234 }
0235 kfree_skb(skb_pipe_info);
0236 }
0237
0238
0239
0240
0241
0242 r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID,
0243 NCI_HCI_LINK_MGMT_GATE,
0244 NCI_HCI_LINK_MGMT_PIPE);
0245
0246 kfree_skb(skb_pipe_list);
0247 return r;
0248 }
0249 EXPORT_SYMBOL_GPL(st_nci_hci_load_session);
0250
0251 static void st_nci_hci_admin_event_received(struct nci_dev *ndev,
0252 u8 event, struct sk_buff *skb)
0253 {
0254 struct st_nci_info *info = nci_get_drvdata(ndev);
0255
0256 switch (event) {
0257 case ST_NCI_EVT_HOT_PLUG:
0258 if (info->se_info.se_active) {
0259 if (!ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(skb)) {
0260 del_timer_sync(&info->se_info.se_active_timer);
0261 info->se_info.se_active = false;
0262 complete(&info->se_info.req_completion);
0263 } else {
0264 mod_timer(&info->se_info.se_active_timer,
0265 jiffies +
0266 msecs_to_jiffies(ST_NCI_SE_TO_PIPES));
0267 }
0268 }
0269 break;
0270 default:
0271 nfc_err(&ndev->nfc_dev->dev, "Unexpected event on admin gate\n");
0272 }
0273 }
0274
0275 static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev,
0276 u8 event,
0277 struct sk_buff *skb)
0278 {
0279 struct st_nci_info *info = nci_get_drvdata(ndev);
0280
0281 pr_debug("apdu reader gate event: %x\n", event);
0282
0283 switch (event) {
0284 case ST_NCI_EVT_TRANSMIT_DATA:
0285 del_timer_sync(&info->se_info.bwi_timer);
0286 info->se_info.bwi_active = false;
0287 info->se_info.cb(info->se_info.cb_context,
0288 skb->data, skb->len, 0);
0289 break;
0290 case ST_NCI_EVT_WTX_REQUEST:
0291 mod_timer(&info->se_info.bwi_timer, jiffies +
0292 msecs_to_jiffies(info->se_info.wt_timeout));
0293 break;
0294 default:
0295 nfc_err(&ndev->nfc_dev->dev, "Unexpected event on apdu reader gate\n");
0296 return 1;
0297 }
0298
0299 kfree_skb(skb);
0300 return 0;
0301 }
0302
0303
0304
0305
0306
0307
0308 static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
0309 u8 host, u8 event,
0310 struct sk_buff *skb)
0311 {
0312 int r = 0;
0313 struct device *dev = &ndev->nfc_dev->dev;
0314 struct nfc_evt_transaction *transaction;
0315
0316 pr_debug("connectivity gate event: %x\n", event);
0317
0318 switch (event) {
0319 case ST_NCI_EVT_CONNECTIVITY:
0320 r = nfc_se_connectivity(ndev->nfc_dev, host);
0321 break;
0322 case ST_NCI_EVT_TRANSACTION:
0323
0324
0325
0326
0327
0328
0329 if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
0330 skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
0331 return -EPROTO;
0332
0333 transaction = devm_kzalloc(dev, skb->len - 2, GFP_KERNEL);
0334 if (!transaction)
0335 return -ENOMEM;
0336
0337 transaction->aid_len = skb->data[1];
0338 memcpy(transaction->aid, &skb->data[2], transaction->aid_len);
0339
0340
0341 if (skb->data[transaction->aid_len + 2] !=
0342 NFC_EVT_TRANSACTION_PARAMS_TAG)
0343 return -EPROTO;
0344
0345 transaction->params_len = skb->data[transaction->aid_len + 3];
0346 memcpy(transaction->params, skb->data +
0347 transaction->aid_len + 4, transaction->params_len);
0348
0349 r = nfc_se_transaction(ndev->nfc_dev, host, transaction);
0350 break;
0351 default:
0352 nfc_err(&ndev->nfc_dev->dev, "Unexpected event on connectivity gate\n");
0353 return 1;
0354 }
0355 kfree_skb(skb);
0356 return r;
0357 }
0358
0359 void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
0360 u8 event, struct sk_buff *skb)
0361 {
0362 u8 gate = ndev->hci_dev->pipes[pipe].gate;
0363 u8 host = ndev->hci_dev->pipes[pipe].host;
0364
0365 switch (gate) {
0366 case NCI_HCI_ADMIN_GATE:
0367 st_nci_hci_admin_event_received(ndev, event, skb);
0368 break;
0369 case ST_NCI_APDU_READER_GATE:
0370 st_nci_hci_apdu_reader_event_received(ndev, event, skb);
0371 break;
0372 case ST_NCI_CONNECTIVITY_GATE:
0373 st_nci_hci_connectivity_event_received(ndev, host, event, skb);
0374 break;
0375 }
0376 }
0377 EXPORT_SYMBOL_GPL(st_nci_hci_event_received);
0378
0379 void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
0380 struct sk_buff *skb)
0381 {
0382 struct st_nci_info *info = nci_get_drvdata(ndev);
0383 u8 gate = ndev->hci_dev->pipes[pipe].gate;
0384
0385 pr_debug("cmd: %x\n", cmd);
0386
0387 switch (cmd) {
0388 case NCI_HCI_ANY_OPEN_PIPE:
0389 if (gate != ST_NCI_APDU_READER_GATE &&
0390 ndev->hci_dev->pipes[pipe].host != ST_NCI_UICC_HOST_ID)
0391 ndev->hci_dev->count_pipes++;
0392
0393 if (ndev->hci_dev->count_pipes ==
0394 ndev->hci_dev->expected_pipes) {
0395 del_timer_sync(&info->se_info.se_active_timer);
0396 info->se_info.se_active = false;
0397 ndev->hci_dev->count_pipes = 0;
0398 complete(&info->se_info.req_completion);
0399 }
0400 break;
0401 }
0402 }
0403 EXPORT_SYMBOL_GPL(st_nci_hci_cmd_received);
0404
0405 static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
0406 u8 state)
0407 {
0408 struct st_nci_info *info = nci_get_drvdata(ndev);
0409 int r, i;
0410 struct sk_buff *sk_host_list;
0411 u8 host_id;
0412
0413 switch (se_idx) {
0414 case ST_NCI_UICC_HOST_ID:
0415 ndev->hci_dev->count_pipes = 0;
0416 ndev->hci_dev->expected_pipes = ST_NCI_SE_COUNT_PIPE_UICC;
0417 break;
0418 case ST_NCI_ESE_HOST_ID:
0419 ndev->hci_dev->count_pipes = 0;
0420 ndev->hci_dev->expected_pipes = ST_NCI_SE_COUNT_PIPE_EMBEDDED;
0421 break;
0422 default:
0423 return -EINVAL;
0424 }
0425
0426
0427
0428
0429
0430 reinit_completion(&info->se_info.req_completion);
0431 r = nci_nfcee_mode_set(ndev, se_idx, state);
0432 if (r != NCI_STATUS_OK)
0433 return r;
0434
0435 mod_timer(&info->se_info.se_active_timer, jiffies +
0436 msecs_to_jiffies(ST_NCI_SE_TO_HOT_PLUG));
0437 info->se_info.se_active = true;
0438
0439
0440 wait_for_completion_interruptible(&info->se_info.req_completion);
0441
0442
0443
0444
0445
0446
0447 if (info->se_info.se_status->is_ese_present &&
0448 info->se_info.se_status->is_uicc_present)
0449 usleep_range(15000, 20000);
0450
0451 r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
0452 NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
0453 if (r != NCI_HCI_ANY_OK)
0454 return r;
0455
0456 for (i = 0; i < sk_host_list->len &&
0457 sk_host_list->data[i] != se_idx; i++)
0458 ;
0459 host_id = sk_host_list->data[i];
0460 kfree_skb(sk_host_list);
0461 if (state == ST_NCI_SE_MODE_ON && host_id == se_idx)
0462 return se_idx;
0463 else if (state == ST_NCI_SE_MODE_OFF && host_id != se_idx)
0464 return se_idx;
0465
0466 return -1;
0467 }
0468
0469 int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
0470 {
0471 int r;
0472
0473
0474
0475
0476
0477
0478 r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_OFF);
0479 if (r < 0) {
0480
0481 if (se_idx == NFC_SE_EMBEDDED) {
0482 r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
0483 ST_NCI_EVT_SE_END_OF_APDU_TRANSFER,
0484 NULL, 0);
0485 }
0486 return r;
0487 }
0488
0489 return 0;
0490 }
0491 EXPORT_SYMBOL_GPL(st_nci_disable_se);
0492
0493 int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
0494 {
0495 int r;
0496
0497
0498
0499
0500
0501
0502 r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_ON);
0503 if (r == ST_NCI_ESE_HOST_ID) {
0504 st_nci_se_get_atr(ndev);
0505 r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
0506 ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
0507 }
0508
0509 if (r < 0) {
0510
0511
0512
0513
0514 nfc_remove_se(ndev->nfc_dev, se_idx);
0515 return r;
0516 }
0517
0518 return 0;
0519 }
0520 EXPORT_SYMBOL_GPL(st_nci_enable_se);
0521
0522 static int st_nci_hci_network_init(struct nci_dev *ndev)
0523 {
0524 struct st_nci_info *info = nci_get_drvdata(ndev);
0525 struct core_conn_create_dest_spec_params *dest_params;
0526 struct dest_spec_params spec_params;
0527 struct nci_conn_info *conn_info;
0528 int r, dev_num;
0529
0530 dest_params =
0531 kzalloc(sizeof(struct core_conn_create_dest_spec_params) +
0532 sizeof(struct dest_spec_params), GFP_KERNEL);
0533 if (dest_params == NULL)
0534 return -ENOMEM;
0535
0536 dest_params->type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE;
0537 dest_params->length = sizeof(struct dest_spec_params);
0538 spec_params.id = ndev->hci_dev->nfcee_id;
0539 spec_params.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS;
0540 memcpy(dest_params->value, &spec_params,
0541 sizeof(struct dest_spec_params));
0542 r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCEE, 1,
0543 sizeof(struct core_conn_create_dest_spec_params) +
0544 sizeof(struct dest_spec_params),
0545 dest_params);
0546 if (r != NCI_STATUS_OK)
0547 goto free_dest_params;
0548
0549 conn_info = ndev->hci_dev->conn_info;
0550 if (!conn_info)
0551 goto free_dest_params;
0552
0553 ndev->hci_dev->init_data.gate_count = ARRAY_SIZE(st_nci_gates);
0554 memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
0555 sizeof(st_nci_gates));
0556
0557
0558
0559
0560
0561 dev_num = find_first_zero_bit(dev_mask, ST_NCI_NUM_DEVICES);
0562 if (dev_num >= ST_NCI_NUM_DEVICES) {
0563 r = -ENODEV;
0564 goto free_dest_params;
0565 }
0566
0567 scnprintf(ndev->hci_dev->init_data.session_id,
0568 sizeof(ndev->hci_dev->init_data.session_id),
0569 "%s%2x", "ST21BH", dev_num);
0570
0571 r = nci_hci_dev_session_init(ndev);
0572 if (r != NCI_HCI_ANY_OK)
0573 goto free_dest_params;
0574
0575
0576
0577
0578
0579
0580 if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
0581 r = nci_nfcee_mode_set(ndev,
0582 ndev->hci_dev->conn_info->dest_params->id,
0583 NCI_NFCEE_DISABLE);
0584 else
0585 r = nci_nfcee_mode_set(ndev,
0586 ndev->hci_dev->conn_info->dest_params->id,
0587 NCI_NFCEE_ENABLE);
0588
0589 free_dest_params:
0590 kfree(dest_params);
0591 return r;
0592 }
0593
0594 int st_nci_discover_se(struct nci_dev *ndev)
0595 {
0596 u8 white_list[2];
0597 int r, wl_size = 0;
0598 int se_count = 0;
0599 struct st_nci_info *info = nci_get_drvdata(ndev);
0600
0601 r = st_nci_hci_network_init(ndev);
0602 if (r != 0)
0603 return r;
0604
0605 if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
0606 return 0;
0607
0608 if (info->se_info.se_status->is_uicc_present)
0609 white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
0610 if (info->se_info.se_status->is_ese_present)
0611 white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
0612
0613 if (wl_size) {
0614 r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
0615 NCI_HCI_ADMIN_PARAM_WHITELIST,
0616 white_list, wl_size);
0617 if (r != NCI_HCI_ANY_OK)
0618 return r;
0619 }
0620
0621 if (info->se_info.se_status->is_uicc_present) {
0622 nfc_add_se(ndev->nfc_dev, ST_NCI_UICC_HOST_ID, NFC_SE_UICC);
0623 se_count++;
0624 }
0625
0626 if (info->se_info.se_status->is_ese_present) {
0627 nfc_add_se(ndev->nfc_dev, ST_NCI_ESE_HOST_ID, NFC_SE_EMBEDDED);
0628 se_count++;
0629 }
0630
0631 return !se_count;
0632 }
0633 EXPORT_SYMBOL_GPL(st_nci_discover_se);
0634
0635 int st_nci_se_io(struct nci_dev *ndev, u32 se_idx,
0636 u8 *apdu, size_t apdu_length,
0637 se_io_cb_t cb, void *cb_context)
0638 {
0639 struct st_nci_info *info = nci_get_drvdata(ndev);
0640
0641 switch (se_idx) {
0642 case ST_NCI_ESE_HOST_ID:
0643 info->se_info.cb = cb;
0644 info->se_info.cb_context = cb_context;
0645 mod_timer(&info->se_info.bwi_timer, jiffies +
0646 msecs_to_jiffies(info->se_info.wt_timeout));
0647 info->se_info.bwi_active = true;
0648 return nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
0649 ST_NCI_EVT_TRANSMIT_DATA, apdu,
0650 apdu_length);
0651 default:
0652 return -ENODEV;
0653 }
0654 }
0655 EXPORT_SYMBOL(st_nci_se_io);
0656
0657 static void st_nci_se_wt_timeout(struct timer_list *t)
0658 {
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669 u8 param = 0x01;
0670 struct st_nci_info *info = from_timer(info, t, se_info.bwi_timer);
0671
0672 info->se_info.bwi_active = false;
0673
0674 if (!info->se_info.xch_error) {
0675 info->se_info.xch_error = true;
0676 nci_hci_send_event(info->ndlc->ndev, ST_NCI_APDU_READER_GATE,
0677 ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
0678 } else {
0679 info->se_info.xch_error = false;
0680 nci_hci_send_event(info->ndlc->ndev, ST_NCI_DEVICE_MGNT_GATE,
0681 ST_NCI_EVT_SE_HARD_RESET, ¶m, 1);
0682 }
0683 info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
0684 }
0685
0686 static void st_nci_se_activation_timeout(struct timer_list *t)
0687 {
0688 struct st_nci_info *info = from_timer(info, t,
0689 se_info.se_active_timer);
0690
0691 info->se_info.se_active = false;
0692
0693 complete(&info->se_info.req_completion);
0694 }
0695
0696 int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status)
0697 {
0698 struct st_nci_info *info = nci_get_drvdata(ndev);
0699
0700 init_completion(&info->se_info.req_completion);
0701
0702 timer_setup(&info->se_info.bwi_timer, st_nci_se_wt_timeout, 0);
0703 info->se_info.bwi_active = false;
0704
0705 timer_setup(&info->se_info.se_active_timer,
0706 st_nci_se_activation_timeout, 0);
0707 info->se_info.se_active = false;
0708
0709 info->se_info.xch_error = false;
0710
0711 info->se_info.wt_timeout =
0712 ST_NCI_BWI_TO_TIMEOUT(ST_NCI_ATR_DEFAULT_BWI);
0713
0714 info->se_info.se_status = se_status;
0715
0716 return 0;
0717 }
0718 EXPORT_SYMBOL(st_nci_se_init);
0719
0720 void st_nci_se_deinit(struct nci_dev *ndev)
0721 {
0722 struct st_nci_info *info = nci_get_drvdata(ndev);
0723
0724 if (info->se_info.bwi_active)
0725 del_timer_sync(&info->se_info.bwi_timer);
0726 if (info->se_info.se_active)
0727 del_timer_sync(&info->se_info.se_active_timer);
0728
0729 info->se_info.se_active = false;
0730 info->se_info.bwi_active = false;
0731 }
0732 EXPORT_SYMBOL(st_nci_se_deinit);
0733