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>
This commit is contained in:
Mark A. Greer 2014-09-23 16:38:05 -07:00 committed by Samuel Ortiz
parent 3bc3f88af5
commit 05afedcb89
2 changed files with 27 additions and 4 deletions

View 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;

View 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)
@ -40,12 +42,13 @@
#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)