summaryrefslogtreecommitdiff
path: root/net/nfc/digital_core.c
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2013-09-19 19:55:29 +0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-09-25 04:02:27 +0400
commit7d0911c02fa2a448a28d7844d2a0c439ff8397b1 (patch)
treec9638f5b6ebab6323c51037a8e871d6cf91d8efd /net/nfc/digital_core.c
parent8c0695e4998dd268ff2a05951961247b7e015651 (diff)
downloadlinux-7d0911c02fa2a448a28d7844d2a0c439ff8397b1.tar.xz
NFC Digital: Add initiator NFC-DEP support
This adds support for NFC-DEP protocol in initiator mode for NFC-A and NFC-F technologies. When a target is detected, the process flow is as follow: For NFC-A technology: 1 - The digital stack receives a SEL_RES as the reply of the SEL_REQ command. 2 - If b7 of SEL_RES is set, the peer device is configure for NFC-DEP protocol. NFC core is notified through nfc_targets_found(). Execution continues at step 4. 3 - Otherwise, it's a tag and the NFC core is notified. Detection ends. 4 - The digital stacks sends an ATR_REQ command containing a randomly generated NFCID3 and the general bytes obtained from the LLCP layer of NFC core. For NFC-F technology: 1 - The digital stack receives a SENSF_RES as the reply of the SENSF_REQ command. 2 - If B1 and B2 of NFCID2 are 0x01 and 0xFE respectively, the peer device is configured for NFC-DEP protocol. NFC core is notified through nfc_targets_found(). Execution continues at step 4. 3 - Otherwise it's a type 3 tag. NFC core is notified. Detection ends. 4 - The digital stacks sends an ATR_REQ command containing the NFC-F NFCID2 as NFCID3 and the general bytes obtained from the LLCP layer of NFC core. For both technologies: 5 - The digital stacks receives the ATR_RES response containing the NFCID3 and the general bytes of the peer device. 6 - The digital stack notifies NFC core that the DEP link is up through nfc_dep_link_up(). 7 - The NFC core performs data exchange through tm_transceive(). 8 - The digital stack sends a DEP_REQ command containing an I PDU with the data from NFC core. 9 - The digital stack receives a DEP_RES command 10 - If the DEP_RES response contains a supervisor PDU with timeout extension request (RTOX) the digital stack sends a DEP_REQ command containing a supervisor PDU acknowledging the RTOX request. The execution continues at step 9. 11 - If the DEP_RES response contains an I PDU, the response data is passed back to NFC core through the response callback. The execution continues at step 8. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/digital_core.c')
-rw-r--r--net/nfc/digital_core.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c
index 25e5bcb946e0..dccfcccf6998 100644
--- a/net/nfc/digital_core.c
+++ b/net/nfc/digital_core.c
@@ -18,9 +18,10 @@
#include "digital.h"
#define DIGITAL_PROTO_NFCA_RF_TECH \
- (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK)
+ (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK)
-#define DIGITAL_PROTO_NFCF_RF_TECH (NFC_PROTO_FELICA_MASK)
+#define DIGITAL_PROTO_NFCF_RF_TECH \
+ (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK)
struct digital_cmd {
struct list_head queue;
@@ -260,6 +261,18 @@ int digital_target_found(struct nfc_digital_dev *ddev,
add_crc = digital_skb_add_crc_f;
break;
+ case NFC_PROTO_NFC_DEP:
+ if (rf_tech == NFC_DIGITAL_RF_TECH_106A) {
+ framing = NFC_DIGITAL_FRAMING_NFCA_NFC_DEP;
+ check_crc = digital_skb_check_crc_a;
+ add_crc = digital_skb_add_crc_a;
+ } else {
+ framing = NFC_DIGITAL_FRAMING_NFCF_NFC_DEP;
+ check_crc = digital_skb_check_crc_f;
+ add_crc = digital_skb_add_crc_f;
+ }
+ break;
+
default:
PR_ERR("Invalid protocol %d", protocol);
return -EINVAL;
@@ -453,12 +466,18 @@ static int digital_dep_link_up(struct nfc_dev *nfc_dev,
struct nfc_target *target,
__u8 comm_mode, __u8 *gb, size_t gb_len)
{
- return -EOPNOTSUPP;
+ struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev);
+
+ return digital_in_send_atr_req(ddev, target, comm_mode, gb, gb_len);
}
static int digital_dep_link_down(struct nfc_dev *nfc_dev)
{
- return -EOPNOTSUPP;
+ struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev);
+
+ ddev->curr_protocol = 0;
+
+ return 0;
}
static int digital_activate_target(struct nfc_dev *nfc_dev,
@@ -523,6 +542,9 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target,
data_exch->cb = cb;
data_exch->cb_context = cb_context;
+ if (ddev->curr_protocol == NFC_PROTO_NFC_DEP)
+ return digital_in_send_dep_req(ddev, target, skb, data_exch);
+
ddev->skb_add_crc(skb);
return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete,
@@ -578,6 +600,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops,
ddev->protocols |= NFC_PROTO_MIFARE_MASK;
if (supported_protocols & NFC_PROTO_FELICA_MASK)
ddev->protocols |= NFC_PROTO_FELICA_MASK;
+ if (supported_protocols & NFC_PROTO_NFC_DEP_MASK)
+ ddev->protocols |= NFC_PROTO_NFC_DEP_MASK;
ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN;
ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN;