diff options
Diffstat (limited to 'net/nfc/nci/core.c')
-rw-r--r-- | net/nfc/nci/core.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index f81efe13985a..acf9abb7d99b 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -176,6 +176,27 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) | |||
176 | (1 + ((*num) * sizeof(struct disc_map_config))), &cmd); | 176 | (1 + ((*num) * sizeof(struct disc_map_config))), &cmd); |
177 | } | 177 | } |
178 | 178 | ||
179 | struct nci_set_config_param { | ||
180 | __u8 id; | ||
181 | size_t len; | ||
182 | __u8 *val; | ||
183 | }; | ||
184 | |||
185 | static void nci_set_config_req(struct nci_dev *ndev, unsigned long opt) | ||
186 | { | ||
187 | struct nci_set_config_param *param = (struct nci_set_config_param *)opt; | ||
188 | struct nci_core_set_config_cmd cmd; | ||
189 | |||
190 | BUG_ON(param->len > NCI_MAX_PARAM_LEN); | ||
191 | |||
192 | cmd.num_params = 1; | ||
193 | cmd.param.id = param->id; | ||
194 | cmd.param.len = param->len; | ||
195 | memcpy(cmd.param.val, param->val, param->len); | ||
196 | |||
197 | nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd); | ||
198 | } | ||
199 | |||
179 | static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | 200 | static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) |
180 | { | 201 | { |
181 | struct nci_rf_disc_cmd cmd; | 202 | struct nci_rf_disc_cmd cmd; |
@@ -388,6 +409,32 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) | |||
388 | return nci_close_device(ndev); | 409 | return nci_close_device(ndev); |
389 | } | 410 | } |
390 | 411 | ||
412 | static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | ||
413 | { | ||
414 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
415 | struct nci_set_config_param param; | ||
416 | __u8 local_gb[NFC_MAX_GT_LEN]; | ||
417 | int i, rc = 0; | ||
418 | |||
419 | param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len); | ||
420 | if ((param.val == NULL) || (param.len == 0)) | ||
421 | return rc; | ||
422 | |||
423 | if (param.len > NCI_MAX_PARAM_LEN) | ||
424 | return -EINVAL; | ||
425 | |||
426 | for (i = 0; i < param.len; i++) | ||
427 | local_gb[param.len-1-i] = param.val[i]; | ||
428 | |||
429 | param.id = NCI_PN_ATR_REQ_GEN_BYTES; | ||
430 | param.val = local_gb; | ||
431 | |||
432 | rc = nci_request(ndev, nci_set_config_req, (unsigned long)¶m, | ||
433 | msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); | ||
434 | |||
435 | return rc; | ||
436 | } | ||
437 | |||
391 | static int nci_start_poll(struct nfc_dev *nfc_dev, | 438 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
392 | __u32 im_protocols, __u32 tm_protocols) | 439 | __u32 im_protocols, __u32 tm_protocols) |
393 | { | 440 | { |
@@ -415,6 +462,14 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, | |||
415 | return -EBUSY; | 462 | return -EBUSY; |
416 | } | 463 | } |
417 | 464 | ||
465 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
466 | rc = nci_set_local_general_bytes(nfc_dev); | ||
467 | if (rc) { | ||
468 | pr_err("failed to set local general bytes\n"); | ||
469 | return rc; | ||
470 | } | ||
471 | } | ||
472 | |||
418 | rc = nci_request(ndev, nci_rf_discover_req, im_protocols, | 473 | rc = nci_request(ndev, nci_rf_discover_req, im_protocols, |
419 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | 474 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); |
420 | 475 | ||
@@ -509,7 +564,7 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
509 | { | 564 | { |
510 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 565 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
511 | 566 | ||
512 | pr_debug("target_idx %d\n", target->idx); | 567 | pr_debug("entry\n"); |
513 | 568 | ||
514 | if (!ndev->target_active_prot) { | 569 | if (!ndev->target_active_prot) { |
515 | pr_err("unable to deactivate target, no active target\n"); | 570 | pr_err("unable to deactivate target, no active target\n"); |
@@ -524,6 +579,38 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
524 | } | 579 | } |
525 | } | 580 | } |
526 | 581 | ||
582 | |||
583 | static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | ||
584 | __u8 comm_mode, __u8 *gb, size_t gb_len) | ||
585 | { | ||
586 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
587 | int rc; | ||
588 | |||
589 | pr_debug("target_idx %d, comm_mode %d\n", target->idx, comm_mode); | ||
590 | |||
591 | rc = nci_activate_target(nfc_dev, target, NFC_PROTO_NFC_DEP); | ||
592 | if (rc) | ||
593 | return rc; | ||
594 | |||
595 | rc = nfc_set_remote_general_bytes(nfc_dev, ndev->remote_gb, | ||
596 | ndev->remote_gb_len); | ||
597 | if (!rc) | ||
598 | rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_PASSIVE, | ||
599 | NFC_RF_INITIATOR); | ||
600 | |||
601 | return rc; | ||
602 | } | ||
603 | |||
604 | static int nci_dep_link_down(struct nfc_dev *nfc_dev) | ||
605 | { | ||
606 | pr_debug("entry\n"); | ||
607 | |||
608 | nci_deactivate_target(nfc_dev, NULL); | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | |||
527 | static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | 614 | static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
528 | struct sk_buff *skb, | 615 | struct sk_buff *skb, |
529 | data_exchange_cb_t cb, void *cb_context) | 616 | data_exchange_cb_t cb, void *cb_context) |
@@ -557,6 +644,8 @@ static struct nfc_ops nci_nfc_ops = { | |||
557 | .dev_down = nci_dev_down, | 644 | .dev_down = nci_dev_down, |
558 | .start_poll = nci_start_poll, | 645 | .start_poll = nci_start_poll, |
559 | .stop_poll = nci_stop_poll, | 646 | .stop_poll = nci_stop_poll, |
647 | .dep_link_up = nci_dep_link_up, | ||
648 | .dep_link_down = nci_dep_link_down, | ||
560 | .activate_target = nci_activate_target, | 649 | .activate_target = nci_activate_target, |
561 | .deactivate_target = nci_deactivate_target, | 650 | .deactivate_target = nci_deactivate_target, |
562 | .im_transceive = nci_transceive, | 651 | .im_transceive = nci_transceive, |