aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2014-09-23 19:38:13 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2014-11-28 06:39:55 -0500
commit384ab1d174a11292af63674a26eaa99864db9b48 (patch)
tree92330bc261e79bc6788543930e590f0fed706b63 /net
parent49dbb14e30c3249f98fe243c3e21b91d10c5c59b (diff)
NFC: digital: Add NFC-DEP Initiator-side ATN Support
When an NFC-DEP Initiator times out when waiting for a DEP_RES from the Target, its supposed to send an ATN to the Target. The Target should respond to the ATN with a similar ATN PDU and the Initiator can then resend the last non-ATN PDU that it sent. No more than 'N(retry,atn)' are to be send where 2 <= 'N(retry,atn)' <= 5. If the Initiator had just sent a NACK PDU when the timeout occurred, it is to continue sending NACKs until 'N(retry,nack)' NACKs have been send. This is described in section 14.12.5.6 of the NFC-DEP Digital Protocol Spec. The digital layer's NFC-DEP code doesn't implement this so add that support. The value chosen for 'N(retry,atn)' is 2. Reviewed-by: Thierry Escande <thierry.escande@linux.intel.com> Tested-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/digital_dep.c104
1 files changed, 98 insertions, 6 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index 31418edbe78e..8f1fefd2ed14 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -18,6 +18,7 @@
18#include "digital.h" 18#include "digital.h"
19 19
20#define DIGITAL_NFC_DEP_N_RETRY_NACK 2 20#define DIGITAL_NFC_DEP_N_RETRY_NACK 2
21#define DIGITAL_NFC_DEP_N_RETRY_ATN 2
21 22
22#define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4 23#define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
23#define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5 24#define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5
@@ -523,10 +524,16 @@ static int digital_in_send_ack(struct nfc_digital_dev *ddev,
523 524
524 ddev->skb_add_crc(skb); 525 ddev->skb_add_crc(skb);
525 526
527 ddev->saved_skb = skb_get(skb);
528 ddev->saved_skb_len = skb->len;
529
526 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, 530 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
527 data_exch); 531 data_exch);
528 if (rc) 532 if (rc) {
529 kfree_skb(skb); 533 kfree_skb(skb);
534 kfree_skb(ddev->saved_skb);
535 ddev->saved_skb = NULL;
536 }
530 537
531 return rc; 538 return rc;
532} 539}
@@ -563,6 +570,37 @@ static int digital_in_send_nack(struct nfc_digital_dev *ddev,
563 return rc; 570 return rc;
564} 571}
565 572
573static int digital_in_send_atn(struct nfc_digital_dev *ddev,
574 struct digital_data_exch *data_exch)
575{
576 struct digital_dep_req_res *dep_req;
577 struct sk_buff *skb;
578 int rc;
579
580 skb = digital_skb_alloc(ddev, 1);
581 if (!skb)
582 return -ENOMEM;
583
584 skb_push(skb, sizeof(struct digital_dep_req_res));
585
586 dep_req = (struct digital_dep_req_res *)skb->data;
587
588 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
589 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
590 dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
591
592 digital_skb_push_dep_sod(ddev, skb);
593
594 ddev->skb_add_crc(skb);
595
596 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
597 data_exch);
598 if (rc)
599 kfree_skb(skb);
600
601 return rc;
602}
603
566static int digital_in_send_rtox(struct nfc_digital_dev *ddev, 604static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
567 struct digital_data_exch *data_exch, u8 rtox) 605 struct digital_data_exch *data_exch, u8 rtox)
568{ 606{
@@ -589,14 +627,30 @@ static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
589 627
590 ddev->skb_add_crc(skb); 628 ddev->skb_add_crc(skb);
591 629
630 ddev->saved_skb = skb_get(skb);
631 ddev->saved_skb_len = skb->len;
632
592 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, 633 rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
593 data_exch); 634 data_exch);
594 if (rc) 635 if (rc) {
595 kfree_skb(skb); 636 kfree_skb(skb);
637 kfree_skb(ddev->saved_skb);
638 ddev->saved_skb = NULL;
639 }
596 640
597 return rc; 641 return rc;
598} 642}
599 643
644static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
645 struct digital_data_exch *data_exch)
646{
647 skb_get(ddev->saved_skb);
648 skb_push(ddev->saved_skb, ddev->saved_skb_len);
649
650 return digital_in_send_cmd(ddev, ddev->saved_skb, 1500,
651 digital_in_recv_dep_res, data_exch);
652}
653
600static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, 654static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
601 struct sk_buff *resp) 655 struct sk_buff *resp)
602{ 656{
@@ -610,13 +664,24 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
610 rc = PTR_ERR(resp); 664 rc = PTR_ERR(resp);
611 resp = NULL; 665 resp = NULL;
612 666
613 if ((rc != -ETIMEDOUT) && 667 if (((rc != -ETIMEDOUT) || ddev->nack_count) &&
614 (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) { 668 (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
669 ddev->atn_count = 0;
670
615 rc = digital_in_send_nack(ddev, data_exch); 671 rc = digital_in_send_nack(ddev, data_exch);
616 if (rc) 672 if (rc)
617 goto error; 673 goto error;
618 674
619 return; 675 return;
676 } else if ((rc == -ETIMEDOUT) &&
677 (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) {
678 ddev->nack_count = 0;
679
680 rc = digital_in_send_atn(ddev, data_exch);
681 if (rc)
682 goto error;
683
684 return;
620 } 685 }
621 686
622 goto exit; 687 goto exit;
@@ -632,6 +697,8 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
632 if (rc) { 697 if (rc) {
633 if ((resp->len >= 4) && 698 if ((resp->len >= 4) &&
634 (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) { 699 (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
700 ddev->atn_count = 0;
701
635 rc = digital_in_send_nack(ddev, data_exch); 702 rc = digital_in_send_nack(ddev, data_exch);
636 if (rc) 703 if (rc)
637 goto error; 704 goto error;
@@ -645,6 +712,7 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
645 goto error; 712 goto error;
646 } 713 }
647 714
715 ddev->atn_count = 0;
648 ddev->nack_count = 0; 716 ddev->nack_count = 0;
649 717
650 if (resp->len > ddev->local_payload_max) { 718 if (resp->len > ddev->local_payload_max) {
@@ -692,6 +760,9 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
692 ddev->curr_nfc_dep_pni = 760 ddev->curr_nfc_dep_pni =
693 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); 761 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
694 762
763 kfree_skb(ddev->saved_skb);
764 ddev->saved_skb = NULL;
765
695 resp = digital_recv_dep_data_gather(ddev, pfb, resp, 766 resp = digital_recv_dep_data_gather(ddev, pfb, resp,
696 digital_in_send_ack, 767 digital_in_send_ack,
697 data_exch); 768 data_exch);
@@ -722,6 +793,9 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
722 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); 793 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
723 794
724 if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { 795 if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
796 kfree_skb(ddev->saved_skb);
797 ddev->saved_skb = NULL;
798
725 rc = digital_in_send_dep_req(ddev, NULL, 799 rc = digital_in_send_dep_req(ddev, NULL,
726 ddev->chaining_skb, 800 ddev->chaining_skb,
727 ddev->data_exch); 801 ddev->data_exch);
@@ -736,11 +810,19 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
736 goto exit; 810 goto exit;
737 811
738 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: 812 case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
739 if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { 813 if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */
740 rc = -EINVAL; 814 rc = digital_in_send_saved_skb(ddev, data_exch);
741 goto error; 815 if (rc) {
816 kfree_skb(ddev->saved_skb);
817 goto error;
818 }
819
820 return;
742 } 821 }
743 822
823 kfree_skb(ddev->saved_skb);
824 ddev->saved_skb = NULL;
825
744 rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]); 826 rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]);
745 if (rc) 827 if (rc)
746 goto error; 828 goto error;
@@ -758,6 +840,9 @@ error:
758 kfree_skb(ddev->chaining_skb); 840 kfree_skb(ddev->chaining_skb);
759 ddev->chaining_skb = NULL; 841 ddev->chaining_skb = NULL;
760 842
843 kfree_skb(ddev->saved_skb);
844 ddev->saved_skb = NULL;
845
761 if (rc) 846 if (rc)
762 kfree_skb(resp); 847 kfree_skb(resp);
763} 848}
@@ -778,6 +863,7 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
778 dep_req->cmd = DIGITAL_CMD_DEP_REQ; 863 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
779 dep_req->pfb = ddev->curr_nfc_dep_pni; 864 dep_req->pfb = ddev->curr_nfc_dep_pni;
780 865
866 ddev->atn_count = 0;
781 ddev->nack_count = 0; 867 ddev->nack_count = 0;
782 868
783 chaining_skb = ddev->chaining_skb; 869 chaining_skb = ddev->chaining_skb;
@@ -790,6 +876,9 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
790 876
791 ddev->skb_add_crc(tmp_skb); 877 ddev->skb_add_crc(tmp_skb);
792 878
879 ddev->saved_skb = skb_get(tmp_skb);
880 ddev->saved_skb_len = tmp_skb->len;
881
793 rc = digital_in_send_cmd(ddev, tmp_skb, 1500, digital_in_recv_dep_res, 882 rc = digital_in_send_cmd(ddev, tmp_skb, 1500, digital_in_recv_dep_res,
794 data_exch); 883 data_exch);
795 if (rc) { 884 if (rc) {
@@ -798,6 +887,9 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
798 887
799 kfree_skb(chaining_skb); 888 kfree_skb(chaining_skb);
800 ddev->chaining_skb = NULL; 889 ddev->chaining_skb = NULL;
890
891 kfree_skb(ddev->saved_skb);
892 ddev->saved_skb = NULL;
801 } 893 }
802 894
803 return rc; 895 return rc;