diff options
-rw-r--r-- | drivers/nfc/pn544_hci.c | 57 | ||||
-rw-r--r-- | include/net/nfc/hci.h | 8 | ||||
-rw-r--r-- | include/net/nfc/shdlc.h | 4 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 57 | ||||
-rw-r--r-- | net/nfc/hci/shdlc.c | 5 |
5 files changed, 92 insertions, 39 deletions
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c index d90aecfce739..a176d1f7bbf3 100644 --- a/drivers/nfc/pn544_hci.c +++ b/drivers/nfc/pn544_hci.c | |||
@@ -148,6 +148,9 @@ struct pn544_hci_info { | |||
148 | * < 0 if hardware error occured (e.g. i2c err) | 148 | * < 0 if hardware error occured (e.g. i2c err) |
149 | * and prevents normal operation. | 149 | * and prevents normal operation. |
150 | */ | 150 | */ |
151 | int async_cb_type; | ||
152 | data_exchange_cb_t async_cb; | ||
153 | void *async_cb_context; | ||
151 | }; | 154 | }; |
152 | 155 | ||
153 | static void pn544_hci_platform_init(struct pn544_hci_info *info) | 156 | static void pn544_hci_platform_init(struct pn544_hci_info *info) |
@@ -731,6 +734,26 @@ static int pn544_hci_complete_target_discovered(struct nfc_shdlc *shdlc, | |||
731 | return r; | 734 | return r; |
732 | } | 735 | } |
733 | 736 | ||
737 | #define PN544_CB_TYPE_READER_F 1 | ||
738 | |||
739 | static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, | ||
740 | int err) | ||
741 | { | ||
742 | struct pn544_hci_info *info = context; | ||
743 | |||
744 | switch (info->async_cb_type) { | ||
745 | case PN544_CB_TYPE_READER_F: | ||
746 | if (err == 0) | ||
747 | skb_pull(skb, 1); | ||
748 | info->async_cb(info->async_cb_context, skb, err); | ||
749 | break; | ||
750 | default: | ||
751 | if (err == 0) | ||
752 | kfree_skb(skb); | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | |||
734 | #define MIFARE_CMD_AUTH_KEY_A 0x60 | 757 | #define MIFARE_CMD_AUTH_KEY_A 0x60 |
735 | #define MIFARE_CMD_AUTH_KEY_B 0x61 | 758 | #define MIFARE_CMD_AUTH_KEY_B 0x61 |
736 | #define MIFARE_CMD_HEADER 2 | 759 | #define MIFARE_CMD_HEADER 2 |
@@ -744,11 +767,11 @@ static int pn544_hci_complete_target_discovered(struct nfc_shdlc *shdlc, | |||
744 | */ | 767 | */ |
745 | static int pn544_hci_data_exchange(struct nfc_shdlc *shdlc, | 768 | static int pn544_hci_data_exchange(struct nfc_shdlc *shdlc, |
746 | struct nfc_target *target, | 769 | struct nfc_target *target, |
747 | struct sk_buff *skb, | 770 | struct sk_buff *skb, data_exchange_cb_t cb, |
748 | struct sk_buff **res_skb) | 771 | void *cb_context) |
749 | { | 772 | { |
773 | struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); | ||
750 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | 774 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); |
751 | int r; | ||
752 | 775 | ||
753 | pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, | 776 | pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, |
754 | target->hci_reader_gate); | 777 | target->hci_reader_gate); |
@@ -773,25 +796,29 @@ static int pn544_hci_data_exchange(struct nfc_shdlc *shdlc, | |||
773 | memcpy(data, uid, MIFARE_UID_LEN); | 796 | memcpy(data, uid, MIFARE_UID_LEN); |
774 | } | 797 | } |
775 | 798 | ||
776 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | 799 | return nfc_hci_send_cmd_async(hdev, |
777 | PN544_MIFARE_CMD, | 800 | target->hci_reader_gate, |
778 | skb->data, skb->len, res_skb); | 801 | PN544_MIFARE_CMD, |
802 | skb->data, skb->len, | ||
803 | cb, cb_context); | ||
779 | } else | 804 | } else |
780 | return 1; | 805 | return 1; |
781 | case PN544_RF_READER_F_GATE: | 806 | case PN544_RF_READER_F_GATE: |
782 | *skb_push(skb, 1) = 0; | 807 | *skb_push(skb, 1) = 0; |
783 | *skb_push(skb, 1) = 0; | 808 | *skb_push(skb, 1) = 0; |
784 | 809 | ||
785 | r = nfc_hci_send_cmd(hdev, target->hci_reader_gate, | 810 | info->async_cb_type = PN544_CB_TYPE_READER_F; |
786 | PN544_FELICA_RAW, | 811 | info->async_cb = cb; |
787 | skb->data, skb->len, res_skb); | 812 | info->async_cb_context = cb_context; |
788 | if (r == 0) | 813 | |
789 | skb_pull(*res_skb, 1); | 814 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
790 | return r; | 815 | PN544_FELICA_RAW, skb->data, |
816 | skb->len, | ||
817 | pn544_hci_data_exchange_cb, info); | ||
791 | case PN544_RF_READER_JEWEL_GATE: | 818 | case PN544_RF_READER_JEWEL_GATE: |
792 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | 819 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
793 | PN544_JEWEL_RAW_CMD, | 820 | PN544_JEWEL_RAW_CMD, skb->data, |
794 | skb->data, skb->len, res_skb); | 821 | skb->len, cb, cb_context); |
795 | default: | 822 | default: |
796 | return 1; | 823 | return 1; |
797 | } | 824 | } |
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 54ba2caab4a6..6cee6e21fc46 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -38,8 +38,8 @@ struct nfc_hci_ops { | |||
38 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, | 38 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
39 | struct nfc_target *target); | 39 | struct nfc_target *target); |
40 | int (*data_exchange) (struct nfc_hci_dev *hdev, | 40 | int (*data_exchange) (struct nfc_hci_dev *hdev, |
41 | struct nfc_target *target, | 41 | struct nfc_target *target, struct sk_buff *skb, |
42 | struct sk_buff *skb, struct sk_buff **res_skb); | 42 | data_exchange_cb_t cb, void *cb_context); |
43 | int (*check_presence)(struct nfc_hci_dev *hdev, | 43 | int (*check_presence)(struct nfc_hci_dev *hdev, |
44 | struct nfc_target *target); | 44 | struct nfc_target *target); |
45 | }; | 45 | }; |
@@ -103,6 +103,10 @@ struct nfc_hci_dev { | |||
103 | u8 hw_mpw; | 103 | u8 hw_mpw; |
104 | u8 hw_software; | 104 | u8 hw_software; |
105 | u8 hw_bsid; | 105 | u8 hw_bsid; |
106 | |||
107 | int async_cb_type; | ||
108 | data_exchange_cb_t async_cb; | ||
109 | void *async_cb_context; | ||
106 | }; | 110 | }; |
107 | 111 | ||
108 | /* hci device allocation */ | 112 | /* hci device allocation */ |
diff --git a/include/net/nfc/shdlc.h b/include/net/nfc/shdlc.h index 342427362989..fe5e19829352 100644 --- a/include/net/nfc/shdlc.h +++ b/include/net/nfc/shdlc.h | |||
@@ -34,8 +34,8 @@ struct nfc_shdlc_ops { | |||
34 | int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, | 34 | int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, |
35 | struct nfc_target *target); | 35 | struct nfc_target *target); |
36 | int (*data_exchange) (struct nfc_shdlc *shdlc, | 36 | int (*data_exchange) (struct nfc_shdlc *shdlc, |
37 | struct nfc_target *target, | 37 | struct nfc_target *target, struct sk_buff *skb, |
38 | struct sk_buff *skb, struct sk_buff **res_skb); | 38 | data_exchange_cb_t cb, void *cb_context); |
39 | int (*check_presence)(struct nfc_shdlc *shdlc, | 39 | int (*check_presence)(struct nfc_shdlc *shdlc, |
40 | struct nfc_target *target); | 40 | struct nfc_target *target); |
41 | }; | 41 | }; |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e387c86e0cc7..dc57e3dc15a4 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -537,13 +537,37 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, | |||
537 | { | 537 | { |
538 | } | 538 | } |
539 | 539 | ||
540 | #define HCI_CB_TYPE_TRANSCEIVE 1 | ||
541 | |||
542 | static void hci_transceive_cb(void *context, struct sk_buff *skb, int err) | ||
543 | { | ||
544 | struct nfc_hci_dev *hdev = context; | ||
545 | |||
546 | switch (hdev->async_cb_type) { | ||
547 | case HCI_CB_TYPE_TRANSCEIVE: | ||
548 | /* | ||
549 | * TODO: Check RF Error indicator to make sure data is valid. | ||
550 | * It seems that HCI cmd can complete without error, but data | ||
551 | * can be invalid if an RF error occured? Ignore for now. | ||
552 | */ | ||
553 | if (err == 0) | ||
554 | skb_trim(skb, skb->len - 1); /* RF Err ind */ | ||
555 | |||
556 | hdev->async_cb(hdev->async_cb_context, skb, err); | ||
557 | break; | ||
558 | default: | ||
559 | if (err == 0) | ||
560 | kfree_skb(skb); | ||
561 | break; | ||
562 | } | ||
563 | } | ||
564 | |||
540 | static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | 565 | static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
541 | struct sk_buff *skb, data_exchange_cb_t cb, | 566 | struct sk_buff *skb, data_exchange_cb_t cb, |
542 | void *cb_context) | 567 | void *cb_context) |
543 | { | 568 | { |
544 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 569 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
545 | int r; | 570 | int r; |
546 | struct sk_buff *res_skb = NULL; | ||
547 | 571 | ||
548 | pr_debug("target_idx=%d\n", target->idx); | 572 | pr_debug("target_idx=%d\n", target->idx); |
549 | 573 | ||
@@ -551,40 +575,37 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
551 | case NFC_HCI_RF_READER_A_GATE: | 575 | case NFC_HCI_RF_READER_A_GATE: |
552 | case NFC_HCI_RF_READER_B_GATE: | 576 | case NFC_HCI_RF_READER_B_GATE: |
553 | if (hdev->ops->data_exchange) { | 577 | if (hdev->ops->data_exchange) { |
554 | r = hdev->ops->data_exchange(hdev, target, skb, | 578 | r = hdev->ops->data_exchange(hdev, target, skb, cb, |
555 | &res_skb); | 579 | cb_context); |
556 | if (r <= 0) /* handled */ | 580 | if (r <= 0) /* handled */ |
557 | break; | 581 | break; |
558 | } | 582 | } |
559 | 583 | ||
560 | *skb_push(skb, 1) = 0; /* CTR, see spec:10.2.2.1 */ | 584 | *skb_push(skb, 1) = 0; /* CTR, see spec:10.2.2.1 */ |
561 | r = nfc_hci_send_cmd(hdev, target->hci_reader_gate, | 585 | |
562 | NFC_HCI_WR_XCHG_DATA, | 586 | hdev->async_cb_type = HCI_CB_TYPE_TRANSCEIVE; |
563 | skb->data, skb->len, &res_skb); | 587 | hdev->async_cb = cb; |
564 | /* | 588 | hdev->async_cb_context = cb_context; |
565 | * TODO: Check RF Error indicator to make sure data is valid. | 589 | |
566 | * It seems that HCI cmd can complete without error, but data | 590 | r = nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
567 | * can be invalid if an RF error occured? Ignore for now. | 591 | NFC_HCI_WR_XCHG_DATA, skb->data, |
568 | */ | 592 | skb->len, hci_transceive_cb, hdev); |
569 | if (r == 0) | ||
570 | skb_trim(res_skb, res_skb->len - 1); /* RF Err ind */ | ||
571 | break; | 593 | break; |
572 | default: | 594 | default: |
573 | if (hdev->ops->data_exchange) { | 595 | if (hdev->ops->data_exchange) { |
574 | r = hdev->ops->data_exchange(hdev, target, skb, | 596 | r = hdev->ops->data_exchange(hdev, target, skb, cb, |
575 | &res_skb); | 597 | cb_context); |
576 | if (r == 1) | 598 | if (r == 1) |
577 | r = -ENOTSUPP; | 599 | r = -ENOTSUPP; |
578 | } | 600 | } |
579 | else | 601 | else |
580 | r = -ENOTSUPP; | 602 | r = -ENOTSUPP; |
603 | break; | ||
581 | } | 604 | } |
582 | 605 | ||
583 | kfree_skb(skb); | 606 | kfree_skb(skb); |
584 | 607 | ||
585 | cb(cb_context, res_skb, r); | 608 | return r; |
586 | |||
587 | return 0; | ||
588 | } | 609 | } |
589 | 610 | ||
590 | static int hci_check_presence(struct nfc_dev *nfc_dev, | 611 | static int hci_check_presence(struct nfc_dev *nfc_dev, |
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c index 9357ba7362f6..c63af7d3e859 100644 --- a/net/nfc/hci/shdlc.c +++ b/net/nfc/hci/shdlc.c | |||
@@ -777,12 +777,13 @@ static int nfc_shdlc_complete_target_discovered(struct nfc_hci_dev *hdev, | |||
777 | static int nfc_shdlc_data_exchange(struct nfc_hci_dev *hdev, | 777 | static int nfc_shdlc_data_exchange(struct nfc_hci_dev *hdev, |
778 | struct nfc_target *target, | 778 | struct nfc_target *target, |
779 | struct sk_buff *skb, | 779 | struct sk_buff *skb, |
780 | struct sk_buff **res_skb) | 780 | data_exchange_cb_t cb, void *cb_context) |
781 | { | 781 | { |
782 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); | 782 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); |
783 | 783 | ||
784 | if (shdlc->ops->data_exchange) | 784 | if (shdlc->ops->data_exchange) |
785 | return shdlc->ops->data_exchange(shdlc, target, skb, res_skb); | 785 | return shdlc->ops->data_exchange(shdlc, target, skb, cb, |
786 | cb_context); | ||
786 | 787 | ||
787 | return -EPERM; | 788 | return -EPERM; |
788 | } | 789 | } |