diff options
Diffstat (limited to 'net/nfc/nci/ntf.c')
| -rw-r--r-- | net/nfc/nci/ntf.c | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 22e453cb787d..3218071072ac 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
| @@ -43,6 +43,7 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
| 43 | struct sk_buff *skb) | 43 | struct sk_buff *skb) |
| 44 | { | 44 | { |
| 45 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; | 45 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; |
| 46 | struct nci_conn_info *conn_info; | ||
| 46 | int i; | 47 | int i; |
| 47 | 48 | ||
| 48 | pr_debug("num_entries %d\n", ntf->num_entries); | 49 | pr_debug("num_entries %d\n", ntf->num_entries); |
| @@ -59,11 +60,13 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
| 59 | i, ntf->conn_entries[i].conn_id, | 60 | i, ntf->conn_entries[i].conn_id, |
| 60 | ntf->conn_entries[i].credits); | 61 | ntf->conn_entries[i].credits); |
| 61 | 62 | ||
| 62 | if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) { | 63 | conn_info = nci_get_conn_info_by_conn_id(ndev, |
| 63 | /* found static rf connection */ | 64 | ntf->conn_entries[i].conn_id); |
| 64 | atomic_add(ntf->conn_entries[i].credits, | 65 | if (!conn_info) |
| 65 | &ndev->credits_cnt); | 66 | return; |
| 66 | } | 67 | |
| 68 | atomic_add(ntf->conn_entries[i].credits, | ||
| 69 | &conn_info->credits_cnt); | ||
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | /* trigger the next tx */ | 72 | /* trigger the next tx */ |
| @@ -96,7 +99,7 @@ static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, | |||
| 96 | 99 | ||
| 97 | /* complete the data exchange transaction, if exists */ | 100 | /* complete the data exchange transaction, if exists */ |
| 98 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | 101 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) |
| 99 | nci_data_exchange_complete(ndev, NULL, -EIO); | 102 | nci_data_exchange_complete(ndev, NULL, ntf->conn_id, -EIO); |
| 100 | } | 103 | } |
| 101 | 104 | ||
| 102 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, | 105 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, |
| @@ -513,6 +516,7 @@ static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev, | |||
| 513 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | 516 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, |
| 514 | struct sk_buff *skb) | 517 | struct sk_buff *skb) |
| 515 | { | 518 | { |
| 519 | struct nci_conn_info *conn_info; | ||
| 516 | struct nci_rf_intf_activated_ntf ntf; | 520 | struct nci_rf_intf_activated_ntf ntf; |
| 517 | __u8 *data = skb->data; | 521 | __u8 *data = skb->data; |
| 518 | int err = NCI_STATUS_OK; | 522 | int err = NCI_STATUS_OK; |
| @@ -537,6 +541,13 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
| 537 | pr_debug("rf_tech_specific_params_len %d\n", | 541 | pr_debug("rf_tech_specific_params_len %d\n", |
| 538 | ntf.rf_tech_specific_params_len); | 542 | ntf.rf_tech_specific_params_len); |
| 539 | 543 | ||
| 544 | /* If this contains a value of 0x00 (NFCEE Direct RF | ||
| 545 | * Interface) then all following parameters SHALL contain a | ||
| 546 | * value of 0 and SHALL be ignored. | ||
| 547 | */ | ||
| 548 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFCEE_DIRECT) | ||
| 549 | goto listen; | ||
| 550 | |||
| 540 | if (ntf.rf_tech_specific_params_len > 0) { | 551 | if (ntf.rf_tech_specific_params_len > 0) { |
| 541 | switch (ntf.activation_rf_tech_and_mode) { | 552 | switch (ntf.activation_rf_tech_and_mode) { |
| 542 | case NCI_NFC_A_PASSIVE_POLL_MODE: | 553 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
| @@ -614,11 +625,16 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
| 614 | 625 | ||
| 615 | exit: | 626 | exit: |
| 616 | if (err == NCI_STATUS_OK) { | 627 | if (err == NCI_STATUS_OK) { |
| 617 | ndev->max_data_pkt_payload_size = ntf.max_data_pkt_payload_size; | 628 | conn_info = ndev->rf_conn_info; |
| 618 | ndev->initial_num_credits = ntf.initial_num_credits; | 629 | if (!conn_info) |
| 630 | return; | ||
| 631 | |||
| 632 | conn_info->max_pkt_payload_len = ntf.max_data_pkt_payload_size; | ||
| 633 | conn_info->initial_num_credits = ntf.initial_num_credits; | ||
| 619 | 634 | ||
| 620 | /* set the available credits to initial value */ | 635 | /* set the available credits to initial value */ |
| 621 | atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); | 636 | atomic_set(&conn_info->credits_cnt, |
| 637 | conn_info->initial_num_credits); | ||
| 622 | 638 | ||
| 623 | /* store general bytes to be reported later in dep_link_up */ | 639 | /* store general bytes to be reported later in dep_link_up */ |
| 624 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { | 640 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { |
| @@ -643,6 +659,7 @@ exit: | |||
| 643 | nci_req_complete(ndev, err); | 659 | nci_req_complete(ndev, err); |
| 644 | } | 660 | } |
| 645 | } else { | 661 | } else { |
| 662 | listen: | ||
| 646 | /* Listen mode */ | 663 | /* Listen mode */ |
| 647 | atomic_set(&ndev->state, NCI_LISTEN_ACTIVE); | 664 | atomic_set(&ndev->state, NCI_LISTEN_ACTIVE); |
| 648 | if (err == NCI_STATUS_OK && | 665 | if (err == NCI_STATUS_OK && |
| @@ -661,10 +678,15 @@ exit: | |||
| 661 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | 678 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, |
| 662 | struct sk_buff *skb) | 679 | struct sk_buff *skb) |
| 663 | { | 680 | { |
| 681 | struct nci_conn_info *conn_info; | ||
| 664 | struct nci_rf_deactivate_ntf *ntf = (void *) skb->data; | 682 | struct nci_rf_deactivate_ntf *ntf = (void *) skb->data; |
| 665 | 683 | ||
| 666 | pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason); | 684 | pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason); |
| 667 | 685 | ||
| 686 | conn_info = ndev->rf_conn_info; | ||
| 687 | if (!conn_info) | ||
| 688 | return; | ||
| 689 | |||
| 668 | /* drop tx data queue */ | 690 | /* drop tx data queue */ |
| 669 | skb_queue_purge(&ndev->tx_q); | 691 | skb_queue_purge(&ndev->tx_q); |
| 670 | 692 | ||
| @@ -676,7 +698,8 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | |||
| 676 | 698 | ||
| 677 | /* complete the data exchange transaction, if exists */ | 699 | /* complete the data exchange transaction, if exists */ |
| 678 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | 700 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) |
| 679 | nci_data_exchange_complete(ndev, NULL, -EIO); | 701 | nci_data_exchange_complete(ndev, NULL, NCI_STATIC_RF_CONN_ID, |
| 702 | -EIO); | ||
| 680 | 703 | ||
| 681 | switch (ntf->type) { | 704 | switch (ntf->type) { |
| 682 | case NCI_DEACTIVATE_TYPE_IDLE_MODE: | 705 | case NCI_DEACTIVATE_TYPE_IDLE_MODE: |
| @@ -696,6 +719,32 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | |||
| 696 | nci_req_complete(ndev, NCI_STATUS_OK); | 719 | nci_req_complete(ndev, NCI_STATUS_OK); |
| 697 | } | 720 | } |
| 698 | 721 | ||
| 722 | static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev, | ||
| 723 | struct sk_buff *skb) | ||
| 724 | { | ||
| 725 | u8 status = NCI_STATUS_OK; | ||
| 726 | struct nci_nfcee_discover_ntf *nfcee_ntf = | ||
| 727 | (struct nci_nfcee_discover_ntf *)skb->data; | ||
| 728 | |||
| 729 | pr_debug("\n"); | ||
| 730 | |||
| 731 | /* NFCForum NCI 9.2.1 HCI Network Specific Handling | ||
| 732 | * If the NFCC supports the HCI Network, it SHALL return one, | ||
| 733 | * and only one, NFCEE_DISCOVER_NTF with a Protocol type of | ||
| 734 | * “HCI Access”, even if the HCI Network contains multiple NFCEEs. | ||
| 735 | */ | ||
| 736 | ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id; | ||
| 737 | ndev->cur_id = nfcee_ntf->nfcee_id; | ||
| 738 | |||
| 739 | nci_req_complete(ndev, status); | ||
| 740 | } | ||
| 741 | |||
| 742 | static void nci_nfcee_action_ntf_packet(struct nci_dev *ndev, | ||
| 743 | struct sk_buff *skb) | ||
| 744 | { | ||
| 745 | pr_debug("\n"); | ||
| 746 | } | ||
| 747 | |||
| 699 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | 748 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) |
| 700 | { | 749 | { |
| 701 | __u16 ntf_opcode = nci_opcode(skb->data); | 750 | __u16 ntf_opcode = nci_opcode(skb->data); |
| @@ -734,6 +783,14 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
| 734 | nci_rf_deactivate_ntf_packet(ndev, skb); | 783 | nci_rf_deactivate_ntf_packet(ndev, skb); |
| 735 | break; | 784 | break; |
| 736 | 785 | ||
| 786 | case NCI_OP_NFCEE_DISCOVER_NTF: | ||
| 787 | nci_nfcee_discover_ntf_packet(ndev, skb); | ||
| 788 | break; | ||
| 789 | |||
| 790 | case NCI_OP_RF_NFCEE_ACTION_NTF: | ||
| 791 | nci_nfcee_action_ntf_packet(ndev, skb); | ||
| 792 | break; | ||
| 793 | |||
| 737 | default: | 794 | default: |
| 738 | pr_err("unknown ntf opcode 0x%x\n", ntf_opcode); | 795 | pr_err("unknown ntf opcode 0x%x\n", ntf_opcode); |
| 739 | break; | 796 | break; |
