aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2014-09-23 19:38:05 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2014-11-28 06:38:24 -0500
commit05afedcb89189df5cea30a13b2a5b4aa70572749 (patch)
treed0ab0bfc4cbe440f44a049724871c5cd90fb048b
parent3bc3f88af5328d369ff399d90f13c566d925c245 (diff)
NFC: digital: Add Target-mode NFC-DEP DID Support
When in Target mode, the Initiator specifies whether subsequent DEP_REQ and DEP_RES frames will include a DID byte by the value passed in the ATR_REQ. If the DID value in the ATR_REQ is '0' then no DID byte will be included. If the DID value is between '1' and '14' then a DID byte containing the same value must be included in subsequent DEP_REQ and DEP_RES frames. Any other DID value is invalid. This is specified in sections 14.8.1.2 and 14.8.2.2 of the NFC Digital Protocol Spec. Checking the DID value (if it should be there at all), is not currently supported by the digital layer's NFC-DEP code. Add this support by remembering the DID value in the ATR_REQ, checking the DID value of received DEP_REQ frames (if it should be there at all), and including the remembered DID value in DEP_RES frames when appropriate. 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>
-rw-r--r--include/net/nfc/digital.h1
-rw-r--r--net/nfc/digital_dep.c30
2 files changed, 27 insertions, 4 deletions
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h
index d9a5cf7ac1c4..80c6183989f3 100644
--- a/include/net/nfc/digital.h
+++ b/include/net/nfc/digital.h
@@ -225,6 +225,7 @@ struct nfc_digital_dev {
225 u8 curr_protocol; 225 u8 curr_protocol;
226 u8 curr_rf_tech; 226 u8 curr_rf_tech;
227 u8 curr_nfc_dep_pni; 227 u8 curr_nfc_dep_pni;
228 u8 did;
228 229
229 u16 target_fsc; 230 u16 target_fsc;
230 231
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index d07c9ab993c8..7d1c794556c3 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -32,6 +32,8 @@
32#define DIGITAL_ATR_REQ_MIN_SIZE 16 32#define DIGITAL_ATR_REQ_MIN_SIZE 16
33#define DIGITAL_ATR_REQ_MAX_SIZE 64 33#define DIGITAL_ATR_REQ_MAX_SIZE 64
34 34
35#define DIGITAL_DID_MAX 14
36
35#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30 37#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
36#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \ 38#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
37 (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4) 39 (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
@@ -40,12 +42,13 @@
40#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) 42#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
41 43
42#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10 44#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
45#define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04
43 46
44#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ 47#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
45 ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT) 48 ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
46#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10) 49#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10)
47#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) 50#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
48#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) 51#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
49#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) 52#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
50 53
51#define DIGITAL_NFC_DEP_PFB_I_PDU 0x00 54#define DIGITAL_NFC_DEP_PFB_I_PDU 0x00
@@ -557,8 +560,17 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
557 560
558 pfb = dep_req->pfb; 561 pfb = dep_req->pfb;
559 562
560 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) 563 if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
561 size++; 564 if (ddev->did && (ddev->did == resp->data[3])) {
565 size++;
566 } else {
567 rc = -EIO;
568 goto exit;
569 }
570 } else if (ddev->did) {
571 rc = -EIO;
572 goto exit;
573 }
562 574
563 if (size > resp->len) { 575 if (size > resp->len) {
564 rc = -EIO; 576 rc = -EIO;
@@ -600,6 +612,13 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
600 dep_res->cmd = DIGITAL_CMD_DEP_RES; 612 dep_res->cmd = DIGITAL_CMD_DEP_RES;
601 dep_res->pfb = ddev->curr_nfc_dep_pni; 613 dep_res->pfb = ddev->curr_nfc_dep_pni;
602 614
615 if (ddev->did) {
616 dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
617
618 memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
619 sizeof(ddev->did));
620 }
621
603 digital_skb_push_dep_sod(ddev, skb); 622 digital_skb_push_dep_sod(ddev, skb);
604 623
605 ddev->skb_add_crc(skb); 624 ddev->skb_add_crc(skb);
@@ -828,11 +847,14 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
828 atr_req = (struct digital_atr_req *)resp->data; 847 atr_req = (struct digital_atr_req *)resp->data;
829 848
830 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || 849 if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
831 atr_req->cmd != DIGITAL_CMD_ATR_REQ) { 850 atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
851 atr_req->did > DIGITAL_DID_MAX) {
832 rc = -EINVAL; 852 rc = -EINVAL;
833 goto exit; 853 goto exit;
834 } 854 }
835 855
856 ddev->did = atr_req->did;
857
836 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, 858 rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
837 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED); 859 NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
838 if (rc) 860 if (rc)