[PATCH 24/30] nfc: netlink: Add suspend_target handler and nfc_reactivate_target

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




In order to manage in a better way the nci poll mode state machine, add
a suspend_target handler. In this way the netlink nfc_genl_activate_target
rely on a new function nfc_reactivate_target calling suspend_target handler
if available (only in nci core).

Signed-off-by: Christophe Ricard <christophe-h.ricard@xxxxxx>
---
 include/net/nfc/nfc.h |  2 ++
 net/nfc/core.c        | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 net/nfc/nci/core.c    | 23 +++++++++++++++++++----
 net/nfc/netlink.c     |  3 +--
 net/nfc/nfc.h         |  2 ++
 5 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 30afc9a..380ab8b 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -67,6 +67,8 @@ struct nfc_ops {
 	int (*dep_link_down)(struct nfc_dev *dev);
 	int (*activate_target)(struct nfc_dev *dev, struct nfc_target *target,
 			       u32 protocol);
+	void (*suspend_target)(struct nfc_dev *dev,
+			       struct nfc_target *target);
 	void (*deactivate_target)(struct nfc_dev *dev,
 				  struct nfc_target *target);
 	int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target,
diff --git a/net/nfc/core.c b/net/nfc/core.c
index cff3f16..70276b6 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -485,6 +485,52 @@ error:
 }
 
 /**
+ * nfc_reactivate_target - reactivate the target for data exchange
+ *
+ * @dev: The nfc device that found the target
+ * @target_idx: index of the target that must be activated
+ * @protocol: nfc protocol that will be used for data exchange
+ */
+int nfc_reactivate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
+{
+	int rc = 0;
+
+	pr_debug("dev_name=%s target_idx=%u\n",
+		 dev_name(&dev->dev), target_idx);
+
+	device_lock(&dev->dev);
+
+	if (!device_is_registered(&dev->dev)) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	if (!dev->active_target) {
+		rc = -ENOTCONN;
+		goto error;
+	}
+
+	if (dev->active_target->idx != target_idx) {
+		rc = -ENOTCONN;
+		goto error;
+	}
+
+	if (dev->ops->check_presence)
+		del_timer_sync(&dev->check_pres_timer);
+
+	if (dev->ops->suspend_target)
+		dev->ops->suspend_target(dev, dev->active_target);
+
+	dev->active_target = NULL;
+	device_unlock(&dev->dev);
+
+	return nfc_activate_target(dev, target_idx, protocol);
+error:
+	device_unlock(&dev->dev);
+	return rc;
+}
+
+/**
  * nfc_data_exchange - transceive data
  *
  * @dev: The nfc device that found the target
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 943889b..b45d6e3 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -800,8 +800,9 @@ static int nci_activate_target(struct nfc_dev *nfc_dev,
 	return rc;
 }
 
-static void nci_deactivate_target(struct nfc_dev *nfc_dev,
-				  struct nfc_target *target)
+static void nci_deactivate_target_mode(struct nfc_dev *nfc_dev,
+				       struct nfc_target *target,
+				       __u8 mode)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 
@@ -815,12 +816,25 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
 	ndev->target_active_prot = 0;
 
 	if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
-		nci_request(ndev, nci_rf_deactivate_req,
-			    NCI_DEACTIVATE_TYPE_IDLE_MODE,
+		nci_request(ndev, nci_rf_deactivate_req, mode,
 			    msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 	}
 }
 
+static void nci_deactivate_target(struct nfc_dev *nfc_dev,
+				  struct nfc_target *target)
+{
+	nci_deactivate_target_mode(nfc_dev, target,
+				   NCI_DEACTIVATE_TYPE_IDLE_MODE);
+}
+
+static void nci_suspend_target(struct nfc_dev *nfc_dev,
+			       struct nfc_target *target)
+{
+	nci_deactivate_target_mode(nfc_dev, target,
+				   NCI_DEACTIVATE_TYPE_SLEEP_MODE);
+}
+
 static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 			   __u8 comm_mode, __u8 *gb, size_t gb_len)
 {
@@ -979,6 +993,7 @@ static struct nfc_ops nci_nfc_ops = {
 	.dep_link_up = nci_dep_link_up,
 	.dep_link_down = nci_dep_link_down,
 	.activate_target = nci_activate_target,
+	.suspend_target = nci_suspend_target,
 	.deactivate_target = nci_deactivate_target,
 	.im_transceive = nci_transceive,
 	.tm_send = nci_tm_send,
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 853172c..bb0e098 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -885,8 +885,7 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
 	target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
 	protocol = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
 
-	nfc_deactivate_target(dev, target_idx);
-	rc = nfc_activate_target(dev, target_idx, protocol);
+	rc = nfc_reactivate_target(dev, target_idx, protocol);
 
 	nfc_put_device(dev);
 	return 0;
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 5c93e84..6250c6e 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -147,6 +147,8 @@ int nfc_dep_link_down(struct nfc_dev *dev);
 
 int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
 
+int nfc_reactivate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
+
 int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
 
 int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux