aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2014-09-23 19:38:09 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2014-11-28 06:39:10 -0500
commit3bd2a5bcc6cd7b8d588aa9ffa947177721eba18e (patch)
tree25d3b453b7733af2144bfff7654aae944240010f /net/nfc
parentb08147cbc4d1b63d65f6c7c522fed9ef3212bc52 (diff)
NFC: digital: Add NFC-DEP Send Chaining Support
When the NFC-DEP code is given a packet to send that is larger than the peer's maximum payload, its supposed to set the 'MI' bit in the 'I' PDU's Protocol Frame Byte (PFB). Setting this bit indicates that NFC-DEP chaining is to occur. When NFC-DEP chaining is progress, sender 'I' PDUs are acknowledged with 'ACK' PDUs until the last 'I' PDU in the chain (which has the 'MI' bit cleared) is responded to with a normal 'I' PDU. This can occur while in Initiator mode or in Target mode. Sender NFC-DEP chaining is currently not implemented in the digital layer so add that support. Unfortunately, since sending a frame may require writing the CRC to the end of the data, the relevant data part of the original skb must be copied for each intermediate frame. 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/nfc')
-rw-r--r--net/nfc/digital_dep.c126
1 files changed, 109 insertions, 17 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index b78790088b8e..e613c294e426 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -42,14 +42,20 @@
42 42
43#define DIGITAL_GB_BIT 0x02 43#define DIGITAL_GB_BIT 0x02
44 44
45#define DIGITAL_NFC_DEP_REQ_RES_HEADROOM 2 /* SoD: [SB (NFC-A)] + LEN */
46#define DIGITAL_NFC_DEP_REQ_RES_TAILROOM 2 /* EoD: 2-byte CRC */
47
45#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) 48#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
46 49
47#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10 50#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
51#define DIGITAL_NFC_DEP_PFB_MI_BIT 0x10
52#define DIGITAL_NFC_DEP_PFB_NACK_BIT 0x10
48#define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04 53#define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04
49 54
50#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ 55#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
51 ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT) 56 ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
52#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10) 57#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT)
58#define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT)
53#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) 59#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
54#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT) 60#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
55#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) 61#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
@@ -161,6 +167,40 @@ static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
161 return 0; 167 return 0;
162} 168}
163 169
170static struct sk_buff *
171digital_send_dep_data_prep(struct nfc_digital_dev *ddev, struct sk_buff *skb,
172 struct digital_dep_req_res *dep_req_res,
173 struct digital_data_exch *data_exch)
174{
175 struct sk_buff *new_skb;
176
177 if (skb->len > ddev->remote_payload_max) {
178 dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT;
179
180 new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max);
181 if (!new_skb) {
182 kfree_skb(ddev->chaining_skb);
183 ddev->chaining_skb = NULL;
184
185 return ERR_PTR(-ENOMEM);
186 }
187
188 skb_reserve(new_skb, ddev->tx_headroom + NFC_HEADER_SIZE +
189 DIGITAL_NFC_DEP_REQ_RES_HEADROOM);
190 memcpy(skb_put(new_skb, ddev->remote_payload_max), skb->data,
191 ddev->remote_payload_max);
192 skb_pull(skb, ddev->remote_payload_max);
193
194 ddev->chaining_skb = skb;
195 ddev->data_exch = data_exch;
196 } else {
197 ddev->chaining_skb = NULL;
198 new_skb = skb;
199 }
200
201 return new_skb;
202}
203
164static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg, 204static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
165 struct sk_buff *resp) 205 struct sk_buff *resp)
166{ 206{
@@ -498,8 +538,6 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
498 break; 538 break;
499 539
500 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: 540 case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
501 pr_err("Received a ACK/NACK PDU\n");
502
503 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { 541 if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
504 PROTOCOL_ERR("14.12.3.3"); 542 PROTOCOL_ERR("14.12.3.3");
505 rc = -EIO; 543 rc = -EIO;
@@ -509,6 +547,17 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
509 ddev->curr_nfc_dep_pni = 547 ddev->curr_nfc_dep_pni =
510 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); 548 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
511 549
550 if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
551 rc = digital_in_send_dep_req(ddev, NULL,
552 ddev->chaining_skb,
553 ddev->data_exch);
554 if (rc)
555 goto error;
556
557 return;
558 }
559
560 pr_err("Received a ACK/NACK PDU\n");
512 rc = -EINVAL; 561 rc = -EINVAL;
513 goto exit; 562 goto exit;
514 563
@@ -538,6 +587,9 @@ exit:
538error: 587error:
539 kfree(data_exch); 588 kfree(data_exch);
540 589
590 kfree_skb(ddev->chaining_skb);
591 ddev->chaining_skb = NULL;
592
541 if (rc) 593 if (rc)
542 kfree_skb(resp); 594 kfree_skb(resp);
543} 595}
@@ -547,23 +599,38 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
547 struct digital_data_exch *data_exch) 599 struct digital_data_exch *data_exch)
548{ 600{
549 struct digital_dep_req_res *dep_req; 601 struct digital_dep_req_res *dep_req;
602 struct sk_buff *chaining_skb, *tmp_skb;
603 int rc;
550 604
551 skb_push(skb, sizeof(struct digital_dep_req_res)); 605 skb_push(skb, sizeof(struct digital_dep_req_res));
552 606
553 if (skb->len > ddev->remote_payload_max)
554 return -EMSGSIZE;
555
556 dep_req = (struct digital_dep_req_res *)skb->data; 607 dep_req = (struct digital_dep_req_res *)skb->data;
608
557 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; 609 dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
558 dep_req->cmd = DIGITAL_CMD_DEP_REQ; 610 dep_req->cmd = DIGITAL_CMD_DEP_REQ;
559 dep_req->pfb = ddev->curr_nfc_dep_pni; 611 dep_req->pfb = ddev->curr_nfc_dep_pni;
560 612
561 digital_skb_push_dep_sod(ddev, skb); 613 chaining_skb = ddev->chaining_skb;
562 614
563 ddev->skb_add_crc(skb); 615 tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch);
616 if (IS_ERR(tmp_skb))
617 return PTR_ERR(tmp_skb);
618
619 digital_skb_push_dep_sod(ddev, tmp_skb);
620
621 ddev->skb_add_crc(tmp_skb);
622
623 rc = digital_in_send_cmd(ddev, tmp_skb, 1500, digital_in_recv_dep_res,
624 data_exch);
625 if (rc) {
626 if (tmp_skb != skb)
627 kfree_skb(tmp_skb);
564 628
565 return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, 629 kfree_skb(chaining_skb);
566 data_exch); 630 ddev->chaining_skb = NULL;
631 }
632
633 return rc;
567} 634}
568 635
569static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech) 636static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
@@ -678,6 +745,14 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
678 goto exit; 745 goto exit;
679 } 746 }
680 747
748 if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
749 rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb);
750 if (rc)
751 goto exit;
752
753 return;
754 }
755
681 pr_err("Received a ACK/NACK PDU\n"); 756 pr_err("Received a ACK/NACK PDU\n");
682 rc = -EINVAL; 757 rc = -EINVAL;
683 goto exit; 758 goto exit;
@@ -690,6 +765,9 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
690 rc = nfc_tm_data_received(ddev->nfc_dev, resp); 765 rc = nfc_tm_data_received(ddev->nfc_dev, resp);
691 766
692exit: 767exit:
768 kfree_skb(ddev->chaining_skb);
769 ddev->chaining_skb = NULL;
770
693 if (rc) 771 if (rc)
694 kfree_skb(resp); 772 kfree_skb(resp);
695} 773}
@@ -697,12 +775,11 @@ exit:
697int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) 775int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
698{ 776{
699 struct digital_dep_req_res *dep_res; 777 struct digital_dep_req_res *dep_res;
778 struct sk_buff *chaining_skb, *tmp_skb;
779 int rc;
700 780
701 skb_push(skb, sizeof(struct digital_dep_req_res)); 781 skb_push(skb, sizeof(struct digital_dep_req_res));
702 782
703 if (skb->len > ddev->remote_payload_max)
704 return -EMSGSIZE;
705
706 dep_res = (struct digital_dep_req_res *)skb->data; 783 dep_res = (struct digital_dep_req_res *)skb->data;
707 784
708 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; 785 dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
@@ -719,12 +796,27 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
719 ddev->curr_nfc_dep_pni = 796 ddev->curr_nfc_dep_pni =
720 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); 797 DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
721 798
722 digital_skb_push_dep_sod(ddev, skb); 799 chaining_skb = ddev->chaining_skb;
723 800
724 ddev->skb_add_crc(skb); 801 tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL);
802 if (IS_ERR(tmp_skb))
803 return PTR_ERR(tmp_skb);
804
805 digital_skb_push_dep_sod(ddev, tmp_skb);
725 806
726 return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req, 807 ddev->skb_add_crc(tmp_skb);
727 NULL); 808
809 rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req,
810 NULL);
811 if (rc) {
812 if (tmp_skb != skb)
813 kfree_skb(tmp_skb);
814
815 kfree_skb(chaining_skb);
816 ddev->chaining_skb = NULL;
817 }
818
819 return rc;
728} 820}
729 821
730static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev, 822static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,