NFC: Implement NCI dep_link_up and dep_link_down
authorIlan Elias <ilane@ti.com>
Wed, 15 Aug 2012 08:46:24 +0000 (11:46 +0300)
committerSamuel Ortiz <sameo@linux.intel.com>
Mon, 24 Sep 2012 22:17:23 +0000 (00:17 +0200)
During NFC-DEP target activation, store the remote
general bytes to be used later in dep_link_up.
When dep_link_up is called, activate the NFC-DEP target,
and forward the remote general bytes.
When dep_link_down is called, deactivate the target.

Signed-off-by: Ilan Elias <ilane@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
include/net/nfc/nci_core.h
include/net/nfc/nfc.h
net/nfc/nci/core.c
net/nfc/nci/ntf.c

index f98674d7baf1ca56251fbe913174aad11333579e..d705d867494987b30da4272fe4c1967a7884412a 100644 (file)
@@ -138,6 +138,10 @@ struct nci_dev {
        data_exchange_cb_t      data_exchange_cb;
        void                    *data_exchange_cb_context;
        struct sk_buff          *rx_data_reassembly;
+
+       /* stored during intf_activated_ntf */
+       __u8 remote_gb[NFC_MAX_GT_LEN];
+       __u8 remote_gb_len;
 };
 
 /* ----- NCI Devices ----- */
index 6431f5e3902217cba706b36f269844242f907856..7b9f71fa0ea7026d34559b29e8a096c6941c2b10 100644 (file)
@@ -72,6 +72,7 @@ struct nfc_ops {
 
 #define NFC_TARGET_IDX_ANY -1
 #define NFC_MAX_GT_LEN 48
+#define NFC_ATR_RES_GT_OFFSET 15
 
 struct nfc_target {
        u32 idx;
index f017b781667afa290c32410e31430ae7de87447c..acf9abb7d99badc592592f83b42f4acbb14ef4de 100644 (file)
@@ -564,7 +564,7 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
 {
        struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 
-       pr_debug("target_idx %d\n", target->idx);
+       pr_debug("entry\n");
 
        if (!ndev->target_active_prot) {
                pr_err("unable to deactivate target, no active target\n");
@@ -579,6 +579,38 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
        }
 }
 
+
+static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
+                          __u8 comm_mode, __u8 *gb, size_t gb_len)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+       int rc;
+
+       pr_debug("target_idx %d, comm_mode %d\n", target->idx, comm_mode);
+
+       rc = nci_activate_target(nfc_dev, target, NFC_PROTO_NFC_DEP);
+       if (rc)
+               return rc;
+
+       rc = nfc_set_remote_general_bytes(nfc_dev, ndev->remote_gb,
+                                         ndev->remote_gb_len);
+       if (!rc)
+               rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_PASSIVE,
+                                       NFC_RF_INITIATOR);
+
+       return rc;
+}
+
+static int nci_dep_link_down(struct nfc_dev *nfc_dev)
+{
+       pr_debug("entry\n");
+
+       nci_deactivate_target(nfc_dev, NULL);
+
+       return 0;
+}
+
+
 static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
                          struct sk_buff *skb,
                          data_exchange_cb_t cb, void *cb_context)
@@ -612,6 +644,8 @@ static struct nfc_ops nci_nfc_ops = {
        .dev_down = nci_dev_down,
        .start_poll = nci_start_poll,
        .stop_poll = nci_stop_poll,
+       .dep_link_up = nci_dep_link_up,
+       .dep_link_down = nci_dep_link_down,
        .activate_target = nci_activate_target,
        .deactivate_target = nci_deactivate_target,
        .im_transceive = nci_transceive,
index 6e17661a41a4158c682bdc7be9fcbf38243a9f45..b2aa98ef0927cb5760f72fb40d016a0b1dcf5575 100644 (file)
@@ -176,6 +176,8 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
                        protocol = NFC_PROTO_ISO14443_B_MASK;
        else if (rf_protocol == NCI_RF_PROTOCOL_T3T)
                protocol = NFC_PROTO_FELICA_MASK;
+       else if (rf_protocol == NCI_RF_PROTOCOL_NFC_DEP)
+               protocol = NFC_PROTO_NFC_DEP_MASK;
        else
                protocol = 0;
 
@@ -505,6 +507,24 @@ exit:
 
                /* set the available credits to initial value */
                atomic_set(&ndev->credits_cnt, ndev->initial_num_credits);
+
+               /* store general bytes to be reported later in dep_link_up */
+               if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
+                       ndev->remote_gb_len = 0;
+
+                       if (ntf.activation_params_len > 0) {
+                               /* ATR_RES general bytes at offset 15 */
+                               ndev->remote_gb_len = min_t(__u8,
+                                       (ntf.activation_params
+                                       .poll_nfc_dep.atr_res_len
+                                       - NFC_ATR_RES_GT_OFFSET),
+                                       NFC_MAX_GT_LEN);
+                               memcpy(ndev->remote_gb,
+                                      (ntf.activation_params.poll_nfc_dep
+                                      .atr_res + NFC_ATR_RES_GT_OFFSET),
+                                      ndev->remote_gb_len);
+                       }
+               }
        }
 
        if (atomic_read(&ndev->state) == NCI_DISCOVERY) {