xref: /openbmc/linux/drivers/nfc/nfcsim.c (revision a440f1aa74da9cb1a77afcfadb12e1d4a78e7e02)
17cbe0ff3SThierry Escande /*
27cbe0ff3SThierry Escande  * NFC hardware simulation driver
37cbe0ff3SThierry Escande  * Copyright (c) 2013, Intel Corporation.
47cbe0ff3SThierry Escande  *
57cbe0ff3SThierry Escande  * This program is free software; you can redistribute it and/or modify it
67cbe0ff3SThierry Escande  * under the terms and conditions of the GNU General Public License,
77cbe0ff3SThierry Escande  * version 2, as published by the Free Software Foundation.
87cbe0ff3SThierry Escande  *
97cbe0ff3SThierry Escande  * This program is distributed in the hope it will be useful, but WITHOUT
107cbe0ff3SThierry Escande  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
117cbe0ff3SThierry Escande  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
127cbe0ff3SThierry Escande  * more details.
137cbe0ff3SThierry Escande  *
147cbe0ff3SThierry Escande  */
157cbe0ff3SThierry Escande 
167cbe0ff3SThierry Escande #include <linux/device.h>
177cbe0ff3SThierry Escande #include <linux/kernel.h>
187cbe0ff3SThierry Escande #include <linux/module.h>
197cbe0ff3SThierry Escande #include <linux/nfc.h>
207cbe0ff3SThierry Escande #include <net/nfc/nfc.h>
217cbe0ff3SThierry Escande 
22073a625fSJoe Perches #define DEV_ERR(_dev, fmt, args...) nfc_err(&_dev->nfc_dev->dev, \
237cbe0ff3SThierry Escande 						"%s: " fmt, __func__, ## args)
247cbe0ff3SThierry Escande 
25b4834839SJoe Perches #define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \
267cbe0ff3SThierry Escande 						"%s: " fmt, __func__, ## args)
277cbe0ff3SThierry Escande 
287cbe0ff3SThierry Escande #define NFCSIM_VERSION "0.1"
297cbe0ff3SThierry Escande 
307cbe0ff3SThierry Escande #define NFCSIM_POLL_NONE	0
317cbe0ff3SThierry Escande #define NFCSIM_POLL_INITIATOR	1
327cbe0ff3SThierry Escande #define NFCSIM_POLL_TARGET	2
337cbe0ff3SThierry Escande #define NFCSIM_POLL_DUAL	(NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET)
347cbe0ff3SThierry Escande 
35*a440f1aaSSaurabh Sengar #define RX_DEFAULT_DELAY	5
36*a440f1aaSSaurabh Sengar 
377cbe0ff3SThierry Escande struct nfcsim {
387cbe0ff3SThierry Escande 	struct nfc_dev *nfc_dev;
397cbe0ff3SThierry Escande 
407cbe0ff3SThierry Escande 	struct mutex lock;
417cbe0ff3SThierry Escande 
427cbe0ff3SThierry Escande 	struct delayed_work recv_work;
437cbe0ff3SThierry Escande 
447cbe0ff3SThierry Escande 	struct sk_buff *clone_skb;
457cbe0ff3SThierry Escande 
467cbe0ff3SThierry Escande 	struct delayed_work poll_work;
477cbe0ff3SThierry Escande 	u8 polling_mode;
487cbe0ff3SThierry Escande 	u8 curr_polling_mode;
497cbe0ff3SThierry Escande 
507cbe0ff3SThierry Escande 	u8 shutting_down;
517cbe0ff3SThierry Escande 
527cbe0ff3SThierry Escande 	u8 up;
537cbe0ff3SThierry Escande 
547cbe0ff3SThierry Escande 	u8 initiator;
557cbe0ff3SThierry Escande 
56*a440f1aaSSaurabh Sengar 	u32 rx_delay;
57*a440f1aaSSaurabh Sengar 
587cbe0ff3SThierry Escande 	data_exchange_cb_t cb;
597cbe0ff3SThierry Escande 	void *cb_context;
607cbe0ff3SThierry Escande 
617cbe0ff3SThierry Escande 	struct nfcsim *peer_dev;
627cbe0ff3SThierry Escande };
637cbe0ff3SThierry Escande 
647cbe0ff3SThierry Escande static struct nfcsim *dev0;
657cbe0ff3SThierry Escande static struct nfcsim *dev1;
667cbe0ff3SThierry Escande 
6740dac370SThierry Escande static struct workqueue_struct *wq;
687cbe0ff3SThierry Escande 
697cbe0ff3SThierry Escande static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown)
707cbe0ff3SThierry Escande {
71b4834839SJoe Perches 	DEV_DBG(dev, "shutdown=%d\n", shutdown);
727cbe0ff3SThierry Escande 
737cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
747cbe0ff3SThierry Escande 
757cbe0ff3SThierry Escande 	dev->polling_mode = NFCSIM_POLL_NONE;
767cbe0ff3SThierry Escande 	dev->shutting_down = shutdown;
777cbe0ff3SThierry Escande 	dev->cb = NULL;
787cbe0ff3SThierry Escande 	dev_kfree_skb(dev->clone_skb);
797cbe0ff3SThierry Escande 	dev->clone_skb = NULL;
807cbe0ff3SThierry Escande 
817cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
827cbe0ff3SThierry Escande 
837cbe0ff3SThierry Escande 	cancel_delayed_work_sync(&dev->poll_work);
847cbe0ff3SThierry Escande 	cancel_delayed_work_sync(&dev->recv_work);
857cbe0ff3SThierry Escande }
867cbe0ff3SThierry Escande 
877cbe0ff3SThierry Escande static int nfcsim_target_found(struct nfcsim *dev)
887cbe0ff3SThierry Escande {
897cbe0ff3SThierry Escande 	struct nfc_target nfc_tgt;
907cbe0ff3SThierry Escande 
91b4834839SJoe Perches 	DEV_DBG(dev, "\n");
927cbe0ff3SThierry Escande 
937cbe0ff3SThierry Escande 	memset(&nfc_tgt, 0, sizeof(struct nfc_target));
947cbe0ff3SThierry Escande 
957cbe0ff3SThierry Escande 	nfc_tgt.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
967cbe0ff3SThierry Escande 	nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
977cbe0ff3SThierry Escande 
987cbe0ff3SThierry Escande 	return 0;
997cbe0ff3SThierry Escande }
1007cbe0ff3SThierry Escande 
1017cbe0ff3SThierry Escande static int nfcsim_dev_up(struct nfc_dev *nfc_dev)
1027cbe0ff3SThierry Escande {
1037cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
1047cbe0ff3SThierry Escande 
105b4834839SJoe Perches 	DEV_DBG(dev, "\n");
1067cbe0ff3SThierry Escande 
1077cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
1087cbe0ff3SThierry Escande 
1097cbe0ff3SThierry Escande 	dev->up = 1;
1107cbe0ff3SThierry Escande 
1117cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
1127cbe0ff3SThierry Escande 
1137cbe0ff3SThierry Escande 	return 0;
1147cbe0ff3SThierry Escande }
1157cbe0ff3SThierry Escande 
1167cbe0ff3SThierry Escande static int nfcsim_dev_down(struct nfc_dev *nfc_dev)
1177cbe0ff3SThierry Escande {
1187cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
1197cbe0ff3SThierry Escande 
120b4834839SJoe Perches 	DEV_DBG(dev, "\n");
1217cbe0ff3SThierry Escande 
1227cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
1237cbe0ff3SThierry Escande 
1247cbe0ff3SThierry Escande 	dev->up = 0;
1257cbe0ff3SThierry Escande 
1267cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
1277cbe0ff3SThierry Escande 
1287cbe0ff3SThierry Escande 	return 0;
1297cbe0ff3SThierry Escande }
1307cbe0ff3SThierry Escande 
1317cbe0ff3SThierry Escande static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev,
1327cbe0ff3SThierry Escande 			      struct nfc_target *target,
1337cbe0ff3SThierry Escande 			      u8 comm_mode, u8 *gb, size_t gb_len)
1347cbe0ff3SThierry Escande {
1357cbe0ff3SThierry Escande 	int rc;
1367cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
1377cbe0ff3SThierry Escande 	struct nfcsim *peer = dev->peer_dev;
1387cbe0ff3SThierry Escande 	u8 *remote_gb;
1397cbe0ff3SThierry Escande 	size_t remote_gb_len;
1407cbe0ff3SThierry Escande 
1417cbe0ff3SThierry Escande 	DEV_DBG(dev, "target_idx: %d, comm_mode: %d\n", target->idx, comm_mode);
1427cbe0ff3SThierry Escande 
1437cbe0ff3SThierry Escande 	mutex_lock(&peer->lock);
1447cbe0ff3SThierry Escande 
1457cbe0ff3SThierry Escande 	nfc_tm_activated(peer->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
1467cbe0ff3SThierry Escande 			 NFC_COMM_ACTIVE, gb, gb_len);
1477cbe0ff3SThierry Escande 
1487cbe0ff3SThierry Escande 	remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len);
1497cbe0ff3SThierry Escande 	if (!remote_gb) {
150073a625fSJoe Perches 		DEV_ERR(peer, "Can't get remote general bytes\n");
1517cbe0ff3SThierry Escande 
1527cbe0ff3SThierry Escande 		mutex_unlock(&peer->lock);
1537cbe0ff3SThierry Escande 		return -EINVAL;
1547cbe0ff3SThierry Escande 	}
1557cbe0ff3SThierry Escande 
1567cbe0ff3SThierry Escande 	mutex_unlock(&peer->lock);
1577cbe0ff3SThierry Escande 
1587cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
1597cbe0ff3SThierry Escande 
1607cbe0ff3SThierry Escande 	rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len);
1617cbe0ff3SThierry Escande 	if (rc) {
162073a625fSJoe Perches 		DEV_ERR(dev, "Can't set remote general bytes\n");
1637cbe0ff3SThierry Escande 		mutex_unlock(&dev->lock);
1647cbe0ff3SThierry Escande 		return rc;
1657cbe0ff3SThierry Escande 	}
1667cbe0ff3SThierry Escande 
1677cbe0ff3SThierry Escande 	rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_ACTIVE,
1687cbe0ff3SThierry Escande 				NFC_RF_INITIATOR);
1697cbe0ff3SThierry Escande 
1707cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
1717cbe0ff3SThierry Escande 
1727cbe0ff3SThierry Escande 	return rc;
1737cbe0ff3SThierry Escande }
1747cbe0ff3SThierry Escande 
1757cbe0ff3SThierry Escande static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev)
1767cbe0ff3SThierry Escande {
1777cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
1787cbe0ff3SThierry Escande 
179b4834839SJoe Perches 	DEV_DBG(dev, "\n");
1807cbe0ff3SThierry Escande 
1817cbe0ff3SThierry Escande 	nfcsim_cleanup_dev(dev, 0);
1827cbe0ff3SThierry Escande 
1837cbe0ff3SThierry Escande 	return 0;
1847cbe0ff3SThierry Escande }
1857cbe0ff3SThierry Escande 
1867cbe0ff3SThierry Escande static int nfcsim_start_poll(struct nfc_dev *nfc_dev,
1877cbe0ff3SThierry Escande 			     u32 im_protocols, u32 tm_protocols)
1887cbe0ff3SThierry Escande {
1897cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
1907cbe0ff3SThierry Escande 	int rc;
1917cbe0ff3SThierry Escande 
1927cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
1937cbe0ff3SThierry Escande 
1947cbe0ff3SThierry Escande 	if (dev->polling_mode != NFCSIM_POLL_NONE) {
195073a625fSJoe Perches 		DEV_ERR(dev, "Already in polling mode\n");
1967cbe0ff3SThierry Escande 		rc = -EBUSY;
1977cbe0ff3SThierry Escande 		goto exit;
1987cbe0ff3SThierry Escande 	}
1997cbe0ff3SThierry Escande 
2007cbe0ff3SThierry Escande 	if (im_protocols & NFC_PROTO_NFC_DEP_MASK)
2017cbe0ff3SThierry Escande 		dev->polling_mode |= NFCSIM_POLL_INITIATOR;
2027cbe0ff3SThierry Escande 
2037cbe0ff3SThierry Escande 	if (tm_protocols & NFC_PROTO_NFC_DEP_MASK)
2047cbe0ff3SThierry Escande 		dev->polling_mode |= NFCSIM_POLL_TARGET;
2057cbe0ff3SThierry Escande 
2067cbe0ff3SThierry Escande 	if (dev->polling_mode == NFCSIM_POLL_NONE) {
207073a625fSJoe Perches 		DEV_ERR(dev, "Unsupported polling mode\n");
2087cbe0ff3SThierry Escande 		rc = -EINVAL;
2097cbe0ff3SThierry Escande 		goto exit;
2107cbe0ff3SThierry Escande 	}
2117cbe0ff3SThierry Escande 
2127cbe0ff3SThierry Escande 	dev->initiator = 0;
2137cbe0ff3SThierry Escande 	dev->curr_polling_mode = NFCSIM_POLL_NONE;
2147cbe0ff3SThierry Escande 
2157cbe0ff3SThierry Escande 	queue_delayed_work(wq, &dev->poll_work, 0);
2167cbe0ff3SThierry Escande 
217b4834839SJoe Perches 	DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X\n", im_protocols,
2187cbe0ff3SThierry Escande 		tm_protocols);
2197cbe0ff3SThierry Escande 
2207cbe0ff3SThierry Escande 	rc = 0;
2217cbe0ff3SThierry Escande exit:
2227cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
2237cbe0ff3SThierry Escande 
2247cbe0ff3SThierry Escande 	return rc;
2257cbe0ff3SThierry Escande }
2267cbe0ff3SThierry Escande 
2277cbe0ff3SThierry Escande static void nfcsim_stop_poll(struct nfc_dev *nfc_dev)
2287cbe0ff3SThierry Escande {
2297cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
2307cbe0ff3SThierry Escande 
231b4834839SJoe Perches 	DEV_DBG(dev, "Stop poll\n");
2327cbe0ff3SThierry Escande 
2337cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
2347cbe0ff3SThierry Escande 
2357cbe0ff3SThierry Escande 	dev->polling_mode = NFCSIM_POLL_NONE;
2367cbe0ff3SThierry Escande 
2377cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
2387cbe0ff3SThierry Escande 
2397cbe0ff3SThierry Escande 	cancel_delayed_work_sync(&dev->poll_work);
2407cbe0ff3SThierry Escande }
2417cbe0ff3SThierry Escande 
2427cbe0ff3SThierry Escande static int nfcsim_activate_target(struct nfc_dev *nfc_dev,
2437cbe0ff3SThierry Escande 				  struct nfc_target *target, u32 protocol)
2447cbe0ff3SThierry Escande {
2457cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
2467cbe0ff3SThierry Escande 
247b4834839SJoe Perches 	DEV_DBG(dev, "\n");
2487cbe0ff3SThierry Escande 
2497cbe0ff3SThierry Escande 	return -ENOTSUPP;
2507cbe0ff3SThierry Escande }
2517cbe0ff3SThierry Escande 
2527cbe0ff3SThierry Escande static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev,
25396d4581fSChristophe Ricard 				     struct nfc_target *target, u8 mode)
2547cbe0ff3SThierry Escande {
2557cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
2567cbe0ff3SThierry Escande 
257b4834839SJoe Perches 	DEV_DBG(dev, "\n");
2587cbe0ff3SThierry Escande }
2597cbe0ff3SThierry Escande 
2607cbe0ff3SThierry Escande static void nfcsim_wq_recv(struct work_struct *work)
2617cbe0ff3SThierry Escande {
2627cbe0ff3SThierry Escande 	struct nfcsim *dev = container_of(work, struct nfcsim,
2637cbe0ff3SThierry Escande 					  recv_work.work);
2647cbe0ff3SThierry Escande 
2657cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
2667cbe0ff3SThierry Escande 
2677cbe0ff3SThierry Escande 	if (dev->shutting_down || !dev->up || !dev->clone_skb) {
2687cbe0ff3SThierry Escande 		dev_kfree_skb(dev->clone_skb);
2697cbe0ff3SThierry Escande 		goto exit;
2707cbe0ff3SThierry Escande 	}
2717cbe0ff3SThierry Escande 
2727cbe0ff3SThierry Escande 	if (dev->initiator) {
2737cbe0ff3SThierry Escande 		if (!dev->cb) {
274073a625fSJoe Perches 			DEV_ERR(dev, "Null recv callback\n");
2757cbe0ff3SThierry Escande 			dev_kfree_skb(dev->clone_skb);
2767cbe0ff3SThierry Escande 			goto exit;
2777cbe0ff3SThierry Escande 		}
2787cbe0ff3SThierry Escande 
2797cbe0ff3SThierry Escande 		dev->cb(dev->cb_context, dev->clone_skb, 0);
2807cbe0ff3SThierry Escande 		dev->cb = NULL;
2817cbe0ff3SThierry Escande 	} else {
2827cbe0ff3SThierry Escande 		nfc_tm_data_received(dev->nfc_dev, dev->clone_skb);
2837cbe0ff3SThierry Escande 	}
2847cbe0ff3SThierry Escande 
2857cbe0ff3SThierry Escande exit:
2867cbe0ff3SThierry Escande 	dev->clone_skb = NULL;
2877cbe0ff3SThierry Escande 
2887cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
2897cbe0ff3SThierry Escande }
2907cbe0ff3SThierry Escande 
2917cbe0ff3SThierry Escande static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target,
2927cbe0ff3SThierry Escande 		     struct sk_buff *skb, data_exchange_cb_t cb,
2937cbe0ff3SThierry Escande 		     void *cb_context)
2947cbe0ff3SThierry Escande {
2957cbe0ff3SThierry Escande 	struct nfcsim *dev = nfc_get_drvdata(nfc_dev);
2967cbe0ff3SThierry Escande 	struct nfcsim *peer = dev->peer_dev;
2977cbe0ff3SThierry Escande 	int err;
2987cbe0ff3SThierry Escande 
2997cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
3007cbe0ff3SThierry Escande 
3017cbe0ff3SThierry Escande 	if (dev->shutting_down || !dev->up) {
3027cbe0ff3SThierry Escande 		mutex_unlock(&dev->lock);
3037cbe0ff3SThierry Escande 		err = -ENODEV;
3047cbe0ff3SThierry Escande 		goto exit;
3057cbe0ff3SThierry Escande 	}
3067cbe0ff3SThierry Escande 
3077cbe0ff3SThierry Escande 	dev->cb = cb;
3087cbe0ff3SThierry Escande 	dev->cb_context = cb_context;
3097cbe0ff3SThierry Escande 
3107cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
3117cbe0ff3SThierry Escande 
3127cbe0ff3SThierry Escande 	mutex_lock(&peer->lock);
3137cbe0ff3SThierry Escande 
3147cbe0ff3SThierry Escande 	peer->clone_skb = skb_clone(skb, GFP_KERNEL);
3157cbe0ff3SThierry Escande 
3167cbe0ff3SThierry Escande 	if (!peer->clone_skb) {
317073a625fSJoe Perches 		DEV_ERR(dev, "skb_clone failed\n");
3187cbe0ff3SThierry Escande 		mutex_unlock(&peer->lock);
3197cbe0ff3SThierry Escande 		err = -ENOMEM;
3207cbe0ff3SThierry Escande 		goto exit;
3217cbe0ff3SThierry Escande 	}
3227cbe0ff3SThierry Escande 
3237cbe0ff3SThierry Escande 	/* This simulates an arbitrary transmission delay between the 2 devices.
3247cbe0ff3SThierry Escande 	 * If packet transmission occurs immediately between them, we have a
3257cbe0ff3SThierry Escande 	 * non-stop flow of several tens of thousands SYMM packets per second
3267cbe0ff3SThierry Escande 	 * and a burning cpu.
3277cbe0ff3SThierry Escande 	 */
328*a440f1aaSSaurabh Sengar 	queue_delayed_work(wq, &peer->recv_work,
329*a440f1aaSSaurabh Sengar 			msecs_to_jiffies(dev->rx_delay));
3307cbe0ff3SThierry Escande 
3317cbe0ff3SThierry Escande 	mutex_unlock(&peer->lock);
3327cbe0ff3SThierry Escande 
3337cbe0ff3SThierry Escande 	err = 0;
3347cbe0ff3SThierry Escande exit:
3357cbe0ff3SThierry Escande 	dev_kfree_skb(skb);
3367cbe0ff3SThierry Escande 
3377cbe0ff3SThierry Escande 	return err;
3387cbe0ff3SThierry Escande }
3397cbe0ff3SThierry Escande 
3407cbe0ff3SThierry Escande static int nfcsim_im_transceive(struct nfc_dev *nfc_dev,
3417cbe0ff3SThierry Escande 				struct nfc_target *target, struct sk_buff *skb,
3427cbe0ff3SThierry Escande 				data_exchange_cb_t cb, void *cb_context)
3437cbe0ff3SThierry Escande {
3447cbe0ff3SThierry Escande 	return nfcsim_tx(nfc_dev, target, skb, cb, cb_context);
3457cbe0ff3SThierry Escande }
3467cbe0ff3SThierry Escande 
3477cbe0ff3SThierry Escande static int nfcsim_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
3487cbe0ff3SThierry Escande {
3497cbe0ff3SThierry Escande 	return nfcsim_tx(nfc_dev, NULL, skb, NULL, NULL);
3507cbe0ff3SThierry Escande }
3517cbe0ff3SThierry Escande 
3527cbe0ff3SThierry Escande static struct nfc_ops nfcsim_nfc_ops = {
3537cbe0ff3SThierry Escande 	.dev_up = nfcsim_dev_up,
3547cbe0ff3SThierry Escande 	.dev_down = nfcsim_dev_down,
3557cbe0ff3SThierry Escande 	.dep_link_up = nfcsim_dep_link_up,
3567cbe0ff3SThierry Escande 	.dep_link_down = nfcsim_dep_link_down,
3577cbe0ff3SThierry Escande 	.start_poll = nfcsim_start_poll,
3587cbe0ff3SThierry Escande 	.stop_poll = nfcsim_stop_poll,
3597cbe0ff3SThierry Escande 	.activate_target = nfcsim_activate_target,
3607cbe0ff3SThierry Escande 	.deactivate_target = nfcsim_deactivate_target,
3617cbe0ff3SThierry Escande 	.im_transceive = nfcsim_im_transceive,
3627cbe0ff3SThierry Escande 	.tm_send = nfcsim_tm_send,
3637cbe0ff3SThierry Escande };
3647cbe0ff3SThierry Escande 
3657cbe0ff3SThierry Escande static void nfcsim_set_polling_mode(struct nfcsim *dev)
3667cbe0ff3SThierry Escande {
3677cbe0ff3SThierry Escande 	if (dev->polling_mode == NFCSIM_POLL_NONE) {
3687cbe0ff3SThierry Escande 		dev->curr_polling_mode = NFCSIM_POLL_NONE;
3697cbe0ff3SThierry Escande 		return;
3707cbe0ff3SThierry Escande 	}
3717cbe0ff3SThierry Escande 
3727cbe0ff3SThierry Escande 	if (dev->curr_polling_mode == NFCSIM_POLL_NONE) {
3737cbe0ff3SThierry Escande 		if (dev->polling_mode & NFCSIM_POLL_INITIATOR)
3747cbe0ff3SThierry Escande 			dev->curr_polling_mode = NFCSIM_POLL_INITIATOR;
3757cbe0ff3SThierry Escande 		else
3767cbe0ff3SThierry Escande 			dev->curr_polling_mode = NFCSIM_POLL_TARGET;
3777cbe0ff3SThierry Escande 
3787cbe0ff3SThierry Escande 		return;
3797cbe0ff3SThierry Escande 	}
3807cbe0ff3SThierry Escande 
3817cbe0ff3SThierry Escande 	if (dev->polling_mode == NFCSIM_POLL_DUAL) {
3827cbe0ff3SThierry Escande 		if (dev->curr_polling_mode == NFCSIM_POLL_TARGET)
3837cbe0ff3SThierry Escande 			dev->curr_polling_mode = NFCSIM_POLL_INITIATOR;
3847cbe0ff3SThierry Escande 		else
3857cbe0ff3SThierry Escande 			dev->curr_polling_mode = NFCSIM_POLL_TARGET;
3867cbe0ff3SThierry Escande 	}
3877cbe0ff3SThierry Escande }
3887cbe0ff3SThierry Escande 
3897cbe0ff3SThierry Escande static void nfcsim_wq_poll(struct work_struct *work)
3907cbe0ff3SThierry Escande {
3917cbe0ff3SThierry Escande 	struct nfcsim *dev = container_of(work, struct nfcsim, poll_work.work);
3927cbe0ff3SThierry Escande 	struct nfcsim *peer = dev->peer_dev;
3937cbe0ff3SThierry Escande 
3947cbe0ff3SThierry Escande 	/* These work items run on an ordered workqueue and are therefore
3957cbe0ff3SThierry Escande 	 * serialized. So we can take both mutexes without being dead locked.
3967cbe0ff3SThierry Escande 	 */
3977cbe0ff3SThierry Escande 	mutex_lock(&dev->lock);
3987cbe0ff3SThierry Escande 	mutex_lock(&peer->lock);
3997cbe0ff3SThierry Escande 
4007cbe0ff3SThierry Escande 	nfcsim_set_polling_mode(dev);
4017cbe0ff3SThierry Escande 
4027cbe0ff3SThierry Escande 	if (dev->curr_polling_mode == NFCSIM_POLL_NONE) {
403b4834839SJoe Perches 		DEV_DBG(dev, "Not polling\n");
4047cbe0ff3SThierry Escande 		goto unlock;
4057cbe0ff3SThierry Escande 	}
4067cbe0ff3SThierry Escande 
4077cbe0ff3SThierry Escande 	DEV_DBG(dev, "Polling as %s",
4087cbe0ff3SThierry Escande 		dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ?
409b4834839SJoe Perches 		"initiator\n" : "target\n");
4107cbe0ff3SThierry Escande 
4117cbe0ff3SThierry Escande 	if (dev->curr_polling_mode == NFCSIM_POLL_TARGET)
4127cbe0ff3SThierry Escande 		goto sched_work;
4137cbe0ff3SThierry Escande 
4147cbe0ff3SThierry Escande 	if (peer->curr_polling_mode == NFCSIM_POLL_TARGET) {
4157cbe0ff3SThierry Escande 		peer->polling_mode = NFCSIM_POLL_NONE;
4167cbe0ff3SThierry Escande 		dev->polling_mode = NFCSIM_POLL_NONE;
4177cbe0ff3SThierry Escande 
4187cbe0ff3SThierry Escande 		dev->initiator = 1;
4197cbe0ff3SThierry Escande 
4207cbe0ff3SThierry Escande 		nfcsim_target_found(dev);
4217cbe0ff3SThierry Escande 
4227cbe0ff3SThierry Escande 		goto unlock;
4237cbe0ff3SThierry Escande 	}
4247cbe0ff3SThierry Escande 
4257cbe0ff3SThierry Escande sched_work:
4267cbe0ff3SThierry Escande 	/* This defines the delay for an initiator to check if the other device
4277cbe0ff3SThierry Escande 	 * is polling in target mode.
4287cbe0ff3SThierry Escande 	 * If the device starts in dual mode polling, it switches between
4297cbe0ff3SThierry Escande 	 * initiator and target at every round.
4307cbe0ff3SThierry Escande 	 * Because the wq is ordered and only 1 work item is executed at a time,
4317cbe0ff3SThierry Escande 	 * we'll always have one device polling as initiator and the other as
4327cbe0ff3SThierry Escande 	 * target at some point, even if both are started in dual mode.
4337cbe0ff3SThierry Escande 	 */
4347cbe0ff3SThierry Escande 	queue_delayed_work(wq, &dev->poll_work, msecs_to_jiffies(200));
4357cbe0ff3SThierry Escande 
4367cbe0ff3SThierry Escande unlock:
4377cbe0ff3SThierry Escande 	mutex_unlock(&peer->lock);
4387cbe0ff3SThierry Escande 	mutex_unlock(&dev->lock);
4397cbe0ff3SThierry Escande }
4407cbe0ff3SThierry Escande 
4417cbe0ff3SThierry Escande static struct nfcsim *nfcsim_init_dev(void)
4427cbe0ff3SThierry Escande {
4437cbe0ff3SThierry Escande 	struct nfcsim *dev;
4447cbe0ff3SThierry Escande 	int rc = -ENOMEM;
4457cbe0ff3SThierry Escande 
4467cbe0ff3SThierry Escande 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
4477cbe0ff3SThierry Escande 	if (dev == NULL)
4487cbe0ff3SThierry Escande 		return ERR_PTR(-ENOMEM);
4497cbe0ff3SThierry Escande 
4507cbe0ff3SThierry Escande 	mutex_init(&dev->lock);
4517cbe0ff3SThierry Escande 
4527cbe0ff3SThierry Escande 	INIT_DELAYED_WORK(&dev->recv_work, nfcsim_wq_recv);
4537cbe0ff3SThierry Escande 	INIT_DELAYED_WORK(&dev->poll_work, nfcsim_wq_poll);
4547cbe0ff3SThierry Escande 
4557cbe0ff3SThierry Escande 	dev->nfc_dev = nfc_allocate_device(&nfcsim_nfc_ops,
4567cbe0ff3SThierry Escande 					   NFC_PROTO_NFC_DEP_MASK,
4577cbe0ff3SThierry Escande 					   0, 0);
4587cbe0ff3SThierry Escande 	if (!dev->nfc_dev)
4597cbe0ff3SThierry Escande 		goto error;
4607cbe0ff3SThierry Escande 
4617cbe0ff3SThierry Escande 	nfc_set_drvdata(dev->nfc_dev, dev);
4627cbe0ff3SThierry Escande 
4637cbe0ff3SThierry Escande 	rc = nfc_register_device(dev->nfc_dev);
4647cbe0ff3SThierry Escande 	if (rc)
4657cbe0ff3SThierry Escande 		goto free_nfc_dev;
4667cbe0ff3SThierry Escande 
467*a440f1aaSSaurabh Sengar 	dev->rx_delay = RX_DEFAULT_DELAY;
4687cbe0ff3SThierry Escande 	return dev;
4697cbe0ff3SThierry Escande 
4707cbe0ff3SThierry Escande free_nfc_dev:
4717cbe0ff3SThierry Escande 	nfc_free_device(dev->nfc_dev);
4727cbe0ff3SThierry Escande 
4737cbe0ff3SThierry Escande error:
4747cbe0ff3SThierry Escande 	kfree(dev);
4757cbe0ff3SThierry Escande 
4767cbe0ff3SThierry Escande 	return ERR_PTR(rc);
4777cbe0ff3SThierry Escande }
4787cbe0ff3SThierry Escande 
4797cbe0ff3SThierry Escande static void nfcsim_free_device(struct nfcsim *dev)
4807cbe0ff3SThierry Escande {
4817cbe0ff3SThierry Escande 	nfc_unregister_device(dev->nfc_dev);
4827cbe0ff3SThierry Escande 
4837cbe0ff3SThierry Escande 	nfc_free_device(dev->nfc_dev);
4847cbe0ff3SThierry Escande 
4857cbe0ff3SThierry Escande 	kfree(dev);
4867cbe0ff3SThierry Escande }
4877cbe0ff3SThierry Escande 
48840dac370SThierry Escande static int __init nfcsim_init(void)
4897cbe0ff3SThierry Escande {
4907cbe0ff3SThierry Escande 	int rc;
4917cbe0ff3SThierry Escande 
4927cbe0ff3SThierry Escande 	/* We need an ordered wq to ensure that poll_work items are executed
4937cbe0ff3SThierry Escande 	 * one at a time.
4947cbe0ff3SThierry Escande 	 */
4957cbe0ff3SThierry Escande 	wq = alloc_ordered_workqueue("nfcsim", 0);
4967cbe0ff3SThierry Escande 	if (!wq) {
4977cbe0ff3SThierry Escande 		rc = -ENOMEM;
4987cbe0ff3SThierry Escande 		goto exit;
4997cbe0ff3SThierry Escande 	}
5007cbe0ff3SThierry Escande 
5017cbe0ff3SThierry Escande 	dev0 = nfcsim_init_dev();
5027cbe0ff3SThierry Escande 	if (IS_ERR(dev0)) {
5037cbe0ff3SThierry Escande 		rc = PTR_ERR(dev0);
5047cbe0ff3SThierry Escande 		goto exit;
5057cbe0ff3SThierry Escande 	}
5067cbe0ff3SThierry Escande 
5077cbe0ff3SThierry Escande 	dev1 = nfcsim_init_dev();
5087cbe0ff3SThierry Escande 	if (IS_ERR(dev1)) {
5097cbe0ff3SThierry Escande 		kfree(dev0);
5107cbe0ff3SThierry Escande 
5117cbe0ff3SThierry Escande 		rc = PTR_ERR(dev1);
5127cbe0ff3SThierry Escande 		goto exit;
5137cbe0ff3SThierry Escande 	}
5147cbe0ff3SThierry Escande 
5157cbe0ff3SThierry Escande 	dev0->peer_dev = dev1;
5167cbe0ff3SThierry Escande 	dev1->peer_dev = dev0;
5177cbe0ff3SThierry Escande 
5187cbe0ff3SThierry Escande 	pr_debug("NFCsim " NFCSIM_VERSION " initialized\n");
5197cbe0ff3SThierry Escande 
5207cbe0ff3SThierry Escande 	rc = 0;
5217cbe0ff3SThierry Escande exit:
5227cbe0ff3SThierry Escande 	if (rc)
5237cbe0ff3SThierry Escande 		pr_err("Failed to initialize nfcsim driver (%d)\n",
5247cbe0ff3SThierry Escande 		       rc);
5257cbe0ff3SThierry Escande 
5267cbe0ff3SThierry Escande 	return rc;
5277cbe0ff3SThierry Escande }
5287cbe0ff3SThierry Escande 
52940dac370SThierry Escande static void __exit nfcsim_exit(void)
5307cbe0ff3SThierry Escande {
5317cbe0ff3SThierry Escande 	nfcsim_cleanup_dev(dev0, 1);
5327cbe0ff3SThierry Escande 	nfcsim_cleanup_dev(dev1, 1);
5337cbe0ff3SThierry Escande 
5347cbe0ff3SThierry Escande 	nfcsim_free_device(dev0);
5357cbe0ff3SThierry Escande 	nfcsim_free_device(dev1);
5367cbe0ff3SThierry Escande 
5377cbe0ff3SThierry Escande 	destroy_workqueue(wq);
5387cbe0ff3SThierry Escande }
5397cbe0ff3SThierry Escande 
5407cbe0ff3SThierry Escande module_init(nfcsim_init);
5417cbe0ff3SThierry Escande module_exit(nfcsim_exit);
5427cbe0ff3SThierry Escande 
5437cbe0ff3SThierry Escande MODULE_DESCRIPTION("NFCSim driver ver " NFCSIM_VERSION);
5447cbe0ff3SThierry Escande MODULE_VERSION(NFCSIM_VERSION);
5457cbe0ff3SThierry Escande MODULE_LICENSE("GPL");
546