]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
NFC: digital: Add Target-mode NFC-DEP DID Support
authorMark A. Greer <mgreer@animalcreek.com>
Tue, 23 Sep 2014 23:38:05 +0000 (16:38 -0700)
committerSamuel Ortiz <sameo@linux.intel.com>
Fri, 28 Nov 2014 11:38:24 +0000 (12:38 +0100)
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>
include/net/nfc/digital.h
net/nfc/digital_dep.c

index d9a5cf7ac1c4750c8418ce867366089e1f133bdc..80c6183989f317f7452c9d5b6cde6754b14d3533 100644 (file)
@@ -225,6 +225,7 @@ struct nfc_digital_dev {
        u8 curr_protocol;
        u8 curr_rf_tech;
        u8 curr_nfc_dep_pni;
+       u8 did;
 
        u16 target_fsc;
 
index d07c9ab993c83ac11770471e60cf6a4fecf9900f..7d1c794556c3f4a3e4dbf97f5b9a41c6ab00d7ae 100644 (file)
@@ -32,6 +32,8 @@
 #define DIGITAL_ATR_REQ_MIN_SIZE 16
 #define DIGITAL_ATR_REQ_MAX_SIZE 64
 
+#define DIGITAL_DID_MAX        14
+
 #define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
 #define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
                                (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
 #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
 
 #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
+#define DIGITAL_NFC_DEP_PFB_DID_BIT    0x04
 
 #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
                                ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
 #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb)  ((pfb) & 0x10)
 #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
-#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
+#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
 #define DIGITAL_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
 
 #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,
 
        pfb = dep_req->pfb;
 
-       if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
-               size++;
+       if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
+               if (ddev->did && (ddev->did == resp->data[3])) {
+                       size++;
+               } else {
+                       rc = -EIO;
+                       goto exit;
+               }
+       } else if (ddev->did) {
+               rc = -EIO;
+               goto exit;
+       }
 
        if (size > resp->len) {
                rc = -EIO;
@@ -600,6 +612,13 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
        dep_res->cmd = DIGITAL_CMD_DEP_RES;
        dep_res->pfb = ddev->curr_nfc_dep_pni;
 
+       if (ddev->did) {
+               dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
+
+               memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
+                      sizeof(ddev->did));
+       }
+
        digital_skb_push_dep_sod(ddev, skb);
 
        ddev->skb_add_crc(skb);
@@ -828,11 +847,14 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
        atr_req = (struct digital_atr_req *)resp->data;
 
        if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
-           atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
+           atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
+           atr_req->did > DIGITAL_DID_MAX) {
                rc = -EINVAL;
                goto exit;
        }
 
+       ddev->did = atr_req->did;
+
        rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
                                     NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
        if (rc)