xref: /openbmc/linux/drivers/nfc/nfcsim.c (revision 204bddcb508fe3bca5c97a9f528bafd7ba8fcec8)
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>
21*204bddcbSThierry Escande #include <net/nfc/digital.h>
227cbe0ff3SThierry Escande 
23*204bddcbSThierry Escande #define NFCSIM_ERR(d, fmt, args...) nfc_err(&d->nfc_digital_dev->nfc_dev->dev, \
247cbe0ff3SThierry Escande 					    "%s: " fmt, __func__, ## args)
257cbe0ff3SThierry Escande 
26*204bddcbSThierry Escande #define NFCSIM_DBG(d, fmt, args...) dev_dbg(&d->nfc_digital_dev->nfc_dev->dev, \
277cbe0ff3SThierry Escande 					    "%s: " fmt, __func__, ## args)
287cbe0ff3SThierry Escande 
29*204bddcbSThierry Escande #define NFCSIM_VERSION "0.2"
307cbe0ff3SThierry Escande 
31*204bddcbSThierry Escande #define NFCSIM_MODE_NONE	0
32*204bddcbSThierry Escande #define NFCSIM_MODE_INITIATOR	1
33*204bddcbSThierry Escande #define NFCSIM_MODE_TARGET	2
347cbe0ff3SThierry Escande 
35*204bddcbSThierry Escande #define NFCSIM_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC   | \
36*204bddcbSThierry Escande 			     NFC_DIGITAL_DRV_CAPS_TG_CRC)
37a440f1aaSSaurabh Sengar 
387cbe0ff3SThierry Escande struct nfcsim {
39*204bddcbSThierry Escande 	struct nfc_digital_dev *nfc_digital_dev;
407cbe0ff3SThierry Escande 
41*204bddcbSThierry Escande 	struct work_struct recv_work;
42*204bddcbSThierry Escande 	struct delayed_work send_work;
437cbe0ff3SThierry Escande 
44*204bddcbSThierry Escande 	struct nfcsim_link *link_in;
45*204bddcbSThierry Escande 	struct nfcsim_link *link_out;
467cbe0ff3SThierry Escande 
47*204bddcbSThierry Escande 	bool up;
48*204bddcbSThierry Escande 	u8 mode;
49*204bddcbSThierry Escande 	u8 rf_tech;
507cbe0ff3SThierry Escande 
51*204bddcbSThierry Escande 	u16 recv_timeout;
527cbe0ff3SThierry Escande 
53*204bddcbSThierry Escande 	nfc_digital_cmd_complete_t cb;
54*204bddcbSThierry Escande 	void *arg;
557cbe0ff3SThierry Escande };
567cbe0ff3SThierry Escande 
57*204bddcbSThierry Escande struct nfcsim_link {
58*204bddcbSThierry Escande 	struct mutex lock;
597cbe0ff3SThierry Escande 
60*204bddcbSThierry Escande 	u8 rf_tech;
61*204bddcbSThierry Escande 	u8 mode;
627cbe0ff3SThierry Escande 
63*204bddcbSThierry Escande 	u8 shutdown;
64*204bddcbSThierry Escande 
65*204bddcbSThierry Escande 	struct sk_buff *skb;
66*204bddcbSThierry Escande 	wait_queue_head_t recv_wait;
67*204bddcbSThierry Escande 	u8 cond;
68*204bddcbSThierry Escande };
69*204bddcbSThierry Escande 
70*204bddcbSThierry Escande static struct nfcsim_link *nfcsim_link_new(void)
717cbe0ff3SThierry Escande {
72*204bddcbSThierry Escande 	struct nfcsim_link *link;
737cbe0ff3SThierry Escande 
74*204bddcbSThierry Escande 	link = kzalloc(sizeof(struct nfcsim_link), GFP_KERNEL);
75*204bddcbSThierry Escande 	if (!link)
76*204bddcbSThierry Escande 		return NULL;
777cbe0ff3SThierry Escande 
78*204bddcbSThierry Escande 	mutex_init(&link->lock);
79*204bddcbSThierry Escande 	init_waitqueue_head(&link->recv_wait);
807cbe0ff3SThierry Escande 
81*204bddcbSThierry Escande 	return link;
827cbe0ff3SThierry Escande }
837cbe0ff3SThierry Escande 
84*204bddcbSThierry Escande static void nfcsim_link_free(struct nfcsim_link *link)
857cbe0ff3SThierry Escande {
86*204bddcbSThierry Escande 	dev_kfree_skb(link->skb);
87*204bddcbSThierry Escande 	kfree(link);
887cbe0ff3SThierry Escande }
897cbe0ff3SThierry Escande 
90*204bddcbSThierry Escande static void nfcsim_link_recv_wake(struct nfcsim_link *link)
917cbe0ff3SThierry Escande {
92*204bddcbSThierry Escande 	link->cond = 1;
93*204bddcbSThierry Escande 	wake_up_interruptible(&link->recv_wait);
947cbe0ff3SThierry Escande }
957cbe0ff3SThierry Escande 
96*204bddcbSThierry Escande static void nfcsim_link_set_skb(struct nfcsim_link *link, struct sk_buff *skb,
97*204bddcbSThierry Escande 				u8 rf_tech, u8 mode)
987cbe0ff3SThierry Escande {
99*204bddcbSThierry Escande 	mutex_lock(&link->lock);
1007cbe0ff3SThierry Escande 
101*204bddcbSThierry Escande 	dev_kfree_skb(link->skb);
102*204bddcbSThierry Escande 	link->skb = skb;
103*204bddcbSThierry Escande 	link->rf_tech = rf_tech;
104*204bddcbSThierry Escande 	link->mode = mode;
1057cbe0ff3SThierry Escande 
106*204bddcbSThierry Escande 	mutex_unlock(&link->lock);
1077cbe0ff3SThierry Escande }
1087cbe0ff3SThierry Escande 
109*204bddcbSThierry Escande static void nfcsim_link_recv_cancel(struct nfcsim_link *link)
110*204bddcbSThierry Escande {
111*204bddcbSThierry Escande 	mutex_lock(&link->lock);
112*204bddcbSThierry Escande 
113*204bddcbSThierry Escande 	link->mode = NFCSIM_MODE_NONE;
114*204bddcbSThierry Escande 
115*204bddcbSThierry Escande 	mutex_unlock(&link->lock);
116*204bddcbSThierry Escande 
117*204bddcbSThierry Escande 	nfcsim_link_recv_wake(link);
118*204bddcbSThierry Escande }
119*204bddcbSThierry Escande 
120*204bddcbSThierry Escande static void nfcsim_link_shutdown(struct nfcsim_link *link)
121*204bddcbSThierry Escande {
122*204bddcbSThierry Escande 	mutex_lock(&link->lock);
123*204bddcbSThierry Escande 
124*204bddcbSThierry Escande 	link->shutdown = 1;
125*204bddcbSThierry Escande 	link->mode = NFCSIM_MODE_NONE;
126*204bddcbSThierry Escande 
127*204bddcbSThierry Escande 	mutex_unlock(&link->lock);
128*204bddcbSThierry Escande 
129*204bddcbSThierry Escande 	nfcsim_link_recv_wake(link);
130*204bddcbSThierry Escande }
131*204bddcbSThierry Escande 
132*204bddcbSThierry Escande static struct sk_buff *nfcsim_link_recv_skb(struct nfcsim_link *link,
133*204bddcbSThierry Escande 					    int timeout, u8 rf_tech, u8 mode)
1347cbe0ff3SThierry Escande {
1357cbe0ff3SThierry Escande 	int rc;
136*204bddcbSThierry Escande 	struct sk_buff *skb;
1377cbe0ff3SThierry Escande 
138*204bddcbSThierry Escande 	rc = wait_event_interruptible_timeout(link->recv_wait,
139*204bddcbSThierry Escande 					      link->cond,
140*204bddcbSThierry Escande 					      msecs_to_jiffies(timeout));
1417cbe0ff3SThierry Escande 
142*204bddcbSThierry Escande 	mutex_lock(&link->lock);
1437cbe0ff3SThierry Escande 
144*204bddcbSThierry Escande 	skb = link->skb;
145*204bddcbSThierry Escande 	link->skb = NULL;
1467cbe0ff3SThierry Escande 
147*204bddcbSThierry Escande 	if (!rc) {
148*204bddcbSThierry Escande 		rc = -ETIMEDOUT;
149*204bddcbSThierry Escande 		goto done;
150*204bddcbSThierry Escande 	}
1517cbe0ff3SThierry Escande 
152*204bddcbSThierry Escande 	if (!skb || link->rf_tech != rf_tech || link->mode == mode) {
153*204bddcbSThierry Escande 		rc = -EINVAL;
154*204bddcbSThierry Escande 		goto done;
155*204bddcbSThierry Escande 	}
156*204bddcbSThierry Escande 
157*204bddcbSThierry Escande 	if (link->shutdown) {
158*204bddcbSThierry Escande 		rc = -ENODEV;
159*204bddcbSThierry Escande 		goto done;
160*204bddcbSThierry Escande 	}
161*204bddcbSThierry Escande 
162*204bddcbSThierry Escande done:
163*204bddcbSThierry Escande 	mutex_unlock(&link->lock);
164*204bddcbSThierry Escande 
165*204bddcbSThierry Escande 	if (rc < 0) {
166*204bddcbSThierry Escande 		dev_kfree_skb(skb);
167*204bddcbSThierry Escande 		skb = ERR_PTR(rc);
168*204bddcbSThierry Escande 	}
169*204bddcbSThierry Escande 
170*204bddcbSThierry Escande 	link->cond = 0;
171*204bddcbSThierry Escande 
172*204bddcbSThierry Escande 	return skb;
173*204bddcbSThierry Escande }
174*204bddcbSThierry Escande 
175*204bddcbSThierry Escande static void nfcsim_send_wq(struct work_struct *work)
176*204bddcbSThierry Escande {
177*204bddcbSThierry Escande 	struct nfcsim *dev = container_of(work, struct nfcsim, send_work.work);
178*204bddcbSThierry Escande 
179*204bddcbSThierry Escande 	/*
180*204bddcbSThierry Escande 	 * To effectively send data, the device just wake up its link_out which
181*204bddcbSThierry Escande 	 * is the link_in of the peer device. The exchanged skb has already been
182*204bddcbSThierry Escande 	 * stored in the dev->link_out through nfcsim_link_set_skb().
183*204bddcbSThierry Escande 	 */
184*204bddcbSThierry Escande 	nfcsim_link_recv_wake(dev->link_out);
185*204bddcbSThierry Escande }
186*204bddcbSThierry Escande 
187*204bddcbSThierry Escande static void nfcsim_recv_wq(struct work_struct *work)
188*204bddcbSThierry Escande {
189*204bddcbSThierry Escande 	struct nfcsim *dev = container_of(work, struct nfcsim, recv_work);
190*204bddcbSThierry Escande 	struct sk_buff *skb;
191*204bddcbSThierry Escande 
192*204bddcbSThierry Escande 	skb = nfcsim_link_recv_skb(dev->link_in, dev->recv_timeout,
193*204bddcbSThierry Escande 				   dev->rf_tech, dev->mode);
194*204bddcbSThierry Escande 
195*204bddcbSThierry Escande 	if (!dev->up) {
196*204bddcbSThierry Escande 		NFCSIM_ERR(dev, "Device is down\n");
197*204bddcbSThierry Escande 
198*204bddcbSThierry Escande 		if (!IS_ERR(skb))
199*204bddcbSThierry Escande 			dev_kfree_skb(skb);
200*204bddcbSThierry Escande 
201*204bddcbSThierry Escande 		skb = ERR_PTR(-ENODEV);
202*204bddcbSThierry Escande 	}
203*204bddcbSThierry Escande 
204*204bddcbSThierry Escande 	dev->cb(dev->nfc_digital_dev, dev->arg, skb);
205*204bddcbSThierry Escande }
206*204bddcbSThierry Escande 
207*204bddcbSThierry Escande static int nfcsim_send(struct nfc_digital_dev *ddev, struct sk_buff *skb,
208*204bddcbSThierry Escande 		       u16 timeout, nfc_digital_cmd_complete_t cb, void *arg)
209*204bddcbSThierry Escande {
210*204bddcbSThierry Escande 	struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
211*204bddcbSThierry Escande 	u8 delay;
212*204bddcbSThierry Escande 
213*204bddcbSThierry Escande 	if (!dev->up) {
214*204bddcbSThierry Escande 		NFCSIM_ERR(dev, "Device is down\n");
215*204bddcbSThierry Escande 		return -ENODEV;
216*204bddcbSThierry Escande 	}
217*204bddcbSThierry Escande 
218*204bddcbSThierry Escande 	dev->recv_timeout = timeout;
219*204bddcbSThierry Escande 	dev->cb = cb;
220*204bddcbSThierry Escande 	dev->arg = arg;
221*204bddcbSThierry Escande 
222*204bddcbSThierry Escande 	schedule_work(&dev->recv_work);
223*204bddcbSThierry Escande 
224*204bddcbSThierry Escande 	if (skb) {
225*204bddcbSThierry Escande 		nfcsim_link_set_skb(dev->link_out, skb, dev->rf_tech,
226*204bddcbSThierry Escande 				    dev->mode);
227*204bddcbSThierry Escande 
228*204bddcbSThierry Escande 		/* Add random delay (between 3 and 10 ms) before sending data */
229*204bddcbSThierry Escande 		get_random_bytes(&delay, 1);
230*204bddcbSThierry Escande 		delay = 3 + (delay & 0x07);
231*204bddcbSThierry Escande 
232*204bddcbSThierry Escande 		schedule_delayed_work(&dev->send_work, msecs_to_jiffies(delay));
233*204bddcbSThierry Escande 	}
234*204bddcbSThierry Escande 
235*204bddcbSThierry Escande 	return 0;
236*204bddcbSThierry Escande }
237*204bddcbSThierry Escande 
238*204bddcbSThierry Escande static void nfcsim_abort_cmd(struct nfc_digital_dev *ddev)
239*204bddcbSThierry Escande {
240*204bddcbSThierry Escande 	struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
241*204bddcbSThierry Escande 
242*204bddcbSThierry Escande 	nfcsim_link_recv_cancel(dev->link_in);
243*204bddcbSThierry Escande }
244*204bddcbSThierry Escande 
245*204bddcbSThierry Escande static int nfcsim_switch_rf(struct nfc_digital_dev *ddev, bool on)
246*204bddcbSThierry Escande {
247*204bddcbSThierry Escande 	struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
248*204bddcbSThierry Escande 
249*204bddcbSThierry Escande 	dev->up = on;
250*204bddcbSThierry Escande 
251*204bddcbSThierry Escande 	return 0;
252*204bddcbSThierry Escande }
253*204bddcbSThierry Escande 
254*204bddcbSThierry Escande static int nfcsim_in_configure_hw(struct nfc_digital_dev *ddev,
255*204bddcbSThierry Escande 					  int type, int param)
256*204bddcbSThierry Escande {
257*204bddcbSThierry Escande 	struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
258*204bddcbSThierry Escande 
259*204bddcbSThierry Escande 	switch (type) {
260*204bddcbSThierry Escande 	case NFC_DIGITAL_CONFIG_RF_TECH:
261*204bddcbSThierry Escande 		dev->up = true;
262*204bddcbSThierry Escande 		dev->mode = NFCSIM_MODE_INITIATOR;
263*204bddcbSThierry Escande 		dev->rf_tech = param;
264*204bddcbSThierry Escande 		break;
265*204bddcbSThierry Escande 
266*204bddcbSThierry Escande 	case NFC_DIGITAL_CONFIG_FRAMING:
267*204bddcbSThierry Escande 		break;
268*204bddcbSThierry Escande 
269*204bddcbSThierry Escande 	default:
270*204bddcbSThierry Escande 		NFCSIM_ERR(dev, "Invalid configuration type: %d\n", type);
2717cbe0ff3SThierry Escande 		return -EINVAL;
2727cbe0ff3SThierry Escande 	}
2737cbe0ff3SThierry Escande 
274*204bddcbSThierry Escande 	return 0;
2757cbe0ff3SThierry Escande }
2767cbe0ff3SThierry Escande 
277*204bddcbSThierry Escande static int nfcsim_in_send_cmd(struct nfc_digital_dev *ddev,
278*204bddcbSThierry Escande 			       struct sk_buff *skb, u16 timeout,
279*204bddcbSThierry Escande 			       nfc_digital_cmd_complete_t cb, void *arg)
2807cbe0ff3SThierry Escande {
281*204bddcbSThierry Escande 	return nfcsim_send(ddev, skb, timeout, cb, arg);
282*204bddcbSThierry Escande }
2837cbe0ff3SThierry Escande 
284*204bddcbSThierry Escande static int nfcsim_tg_configure_hw(struct nfc_digital_dev *ddev,
285*204bddcbSThierry Escande 					  int type, int param)
286*204bddcbSThierry Escande {
287*204bddcbSThierry Escande 	struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
2887cbe0ff3SThierry Escande 
289*204bddcbSThierry Escande 	switch (type) {
290*204bddcbSThierry Escande 	case NFC_DIGITAL_CONFIG_RF_TECH:
291*204bddcbSThierry Escande 		dev->up = true;
292*204bddcbSThierry Escande 		dev->mode = NFCSIM_MODE_TARGET;
293*204bddcbSThierry Escande 		dev->rf_tech = param;
294*204bddcbSThierry Escande 		break;
295*204bddcbSThierry Escande 
296*204bddcbSThierry Escande 	case NFC_DIGITAL_CONFIG_FRAMING:
297*204bddcbSThierry Escande 		break;
298*204bddcbSThierry Escande 
299*204bddcbSThierry Escande 	default:
300*204bddcbSThierry Escande 		NFCSIM_ERR(dev, "Invalid configuration type: %d\n", type);
301*204bddcbSThierry Escande 		return -EINVAL;
302*204bddcbSThierry Escande 	}
3037cbe0ff3SThierry Escande 
3047cbe0ff3SThierry Escande 	return 0;
3057cbe0ff3SThierry Escande }
3067cbe0ff3SThierry Escande 
307*204bddcbSThierry Escande static int nfcsim_tg_send_cmd(struct nfc_digital_dev *ddev,
308*204bddcbSThierry Escande 			       struct sk_buff *skb, u16 timeout,
309*204bddcbSThierry Escande 			       nfc_digital_cmd_complete_t cb, void *arg)
3107cbe0ff3SThierry Escande {
311*204bddcbSThierry Escande 	return nfcsim_send(ddev, skb, timeout, cb, arg);
3127cbe0ff3SThierry Escande }
3137cbe0ff3SThierry Escande 
314*204bddcbSThierry Escande static int nfcsim_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
315*204bddcbSThierry Escande 			    nfc_digital_cmd_complete_t cb, void *arg)
3167cbe0ff3SThierry Escande {
317*204bddcbSThierry Escande 	return nfcsim_send(ddev, NULL, timeout, cb, arg);
3187cbe0ff3SThierry Escande }
3197cbe0ff3SThierry Escande 
320*204bddcbSThierry Escande static struct nfc_digital_ops nfcsim_digital_ops = {
321*204bddcbSThierry Escande 	.in_configure_hw = nfcsim_in_configure_hw,
322*204bddcbSThierry Escande 	.in_send_cmd = nfcsim_in_send_cmd,
3237cbe0ff3SThierry Escande 
324*204bddcbSThierry Escande 	.tg_listen = nfcsim_tg_listen,
325*204bddcbSThierry Escande 	.tg_configure_hw = nfcsim_tg_configure_hw,
326*204bddcbSThierry Escande 	.tg_send_cmd = nfcsim_tg_send_cmd,
3277cbe0ff3SThierry Escande 
328*204bddcbSThierry Escande 	.abort_cmd = nfcsim_abort_cmd,
329*204bddcbSThierry Escande 	.switch_rf = nfcsim_switch_rf,
3307cbe0ff3SThierry Escande };
3317cbe0ff3SThierry Escande 
332*204bddcbSThierry Escande static struct nfcsim *nfcsim_device_new(struct nfcsim_link *link_in,
333*204bddcbSThierry Escande 					struct nfcsim_link *link_out)
3347cbe0ff3SThierry Escande {
3357cbe0ff3SThierry Escande 	struct nfcsim *dev;
336*204bddcbSThierry Escande 	int rc;
3377cbe0ff3SThierry Escande 
338*204bddcbSThierry Escande 	dev = kzalloc(sizeof(struct nfcsim), GFP_KERNEL);
339*204bddcbSThierry Escande 	if (!dev)
3407cbe0ff3SThierry Escande 		return ERR_PTR(-ENOMEM);
3417cbe0ff3SThierry Escande 
342*204bddcbSThierry Escande 	INIT_DELAYED_WORK(&dev->send_work, nfcsim_send_wq);
343*204bddcbSThierry Escande 	INIT_WORK(&dev->recv_work, nfcsim_recv_wq);
3447cbe0ff3SThierry Escande 
345*204bddcbSThierry Escande 	dev->nfc_digital_dev =
346*204bddcbSThierry Escande 			nfc_digital_allocate_device(&nfcsim_digital_ops,
3477cbe0ff3SThierry Escande 						    NFC_PROTO_NFC_DEP_MASK,
348*204bddcbSThierry Escande 						    NFCSIM_CAPABILITIES,
3497cbe0ff3SThierry Escande 						    0, 0);
350*204bddcbSThierry Escande 	if (!dev->nfc_digital_dev) {
351*204bddcbSThierry Escande 		kfree(dev);
352*204bddcbSThierry Escande 		return ERR_PTR(-ENOMEM);
353*204bddcbSThierry Escande 	}
3547cbe0ff3SThierry Escande 
355*204bddcbSThierry Escande 	nfc_digital_set_drvdata(dev->nfc_digital_dev, dev);
3567cbe0ff3SThierry Escande 
357*204bddcbSThierry Escande 	dev->link_in = link_in;
358*204bddcbSThierry Escande 	dev->link_out = link_out;
3597cbe0ff3SThierry Escande 
360*204bddcbSThierry Escande 	rc = nfc_digital_register_device(dev->nfc_digital_dev);
361*204bddcbSThierry Escande 	if (rc) {
362*204bddcbSThierry Escande 		pr_err("Could not register digital device (%d)\n", rc);
363*204bddcbSThierry Escande 		nfc_digital_free_device(dev->nfc_digital_dev);
3647cbe0ff3SThierry Escande 		kfree(dev);
3657cbe0ff3SThierry Escande 
3667cbe0ff3SThierry Escande 		return ERR_PTR(rc);
3677cbe0ff3SThierry Escande 	}
3687cbe0ff3SThierry Escande 
369*204bddcbSThierry Escande 	return dev;
370*204bddcbSThierry Escande }
3717cbe0ff3SThierry Escande 
372*204bddcbSThierry Escande static void nfcsim_device_free(struct nfcsim *dev)
373*204bddcbSThierry Escande {
374*204bddcbSThierry Escande 	nfc_digital_unregister_device(dev->nfc_digital_dev);
375*204bddcbSThierry Escande 
376*204bddcbSThierry Escande 	dev->up = false;
377*204bddcbSThierry Escande 
378*204bddcbSThierry Escande 	nfcsim_link_shutdown(dev->link_in);
379*204bddcbSThierry Escande 
380*204bddcbSThierry Escande 	cancel_delayed_work_sync(&dev->send_work);
381*204bddcbSThierry Escande 	cancel_work_sync(&dev->recv_work);
382*204bddcbSThierry Escande 
383*204bddcbSThierry Escande 	nfc_digital_free_device(dev->nfc_digital_dev);
3847cbe0ff3SThierry Escande 
3857cbe0ff3SThierry Escande 	kfree(dev);
3867cbe0ff3SThierry Escande }
3877cbe0ff3SThierry Escande 
388*204bddcbSThierry Escande static struct nfcsim *dev0;
389*204bddcbSThierry Escande static struct nfcsim *dev1;
390*204bddcbSThierry Escande 
39140dac370SThierry Escande static int __init nfcsim_init(void)
3927cbe0ff3SThierry Escande {
393*204bddcbSThierry Escande 	struct nfcsim_link *link0, *link1;
3947cbe0ff3SThierry Escande 	int rc;
3957cbe0ff3SThierry Escande 
396*204bddcbSThierry Escande 	link0 = nfcsim_link_new();
397*204bddcbSThierry Escande 	link1 = nfcsim_link_new();
398*204bddcbSThierry Escande 	if (!link0 || !link1) {
3997cbe0ff3SThierry Escande 		rc = -ENOMEM;
400*204bddcbSThierry Escande 		goto exit_err;
4017cbe0ff3SThierry Escande 	}
4027cbe0ff3SThierry Escande 
403*204bddcbSThierry Escande 	dev0 = nfcsim_device_new(link0, link1);
4047cbe0ff3SThierry Escande 	if (IS_ERR(dev0)) {
4057cbe0ff3SThierry Escande 		rc = PTR_ERR(dev0);
406*204bddcbSThierry Escande 		goto exit_err;
4077cbe0ff3SThierry Escande 	}
4087cbe0ff3SThierry Escande 
409*204bddcbSThierry Escande 	dev1 = nfcsim_device_new(link1, link0);
4107cbe0ff3SThierry Escande 	if (IS_ERR(dev1)) {
411*204bddcbSThierry Escande 		nfcsim_device_free(dev0);
4127cbe0ff3SThierry Escande 
4137cbe0ff3SThierry Escande 		rc = PTR_ERR(dev1);
414*204bddcbSThierry Escande 		goto exit_err;
4157cbe0ff3SThierry Escande 	}
4167cbe0ff3SThierry Escande 
417*204bddcbSThierry Escande 	pr_info("nfcsim " NFCSIM_VERSION " initialized\n");
4187cbe0ff3SThierry Escande 
419*204bddcbSThierry Escande 	return 0;
4207cbe0ff3SThierry Escande 
421*204bddcbSThierry Escande exit_err:
422*204bddcbSThierry Escande 	pr_err("Failed to initialize nfcsim driver (%d)\n", rc);
423*204bddcbSThierry Escande 
424*204bddcbSThierry Escande 	nfcsim_link_free(link0);
425*204bddcbSThierry Escande 	nfcsim_link_free(link1);
4267cbe0ff3SThierry Escande 
4277cbe0ff3SThierry Escande 	return rc;
4287cbe0ff3SThierry Escande }
4297cbe0ff3SThierry Escande 
43040dac370SThierry Escande static void __exit nfcsim_exit(void)
4317cbe0ff3SThierry Escande {
432*204bddcbSThierry Escande 	struct nfcsim_link *link0, *link1;
4337cbe0ff3SThierry Escande 
434*204bddcbSThierry Escande 	link0 = dev0->link_in;
435*204bddcbSThierry Escande 	link1 = dev0->link_out;
4367cbe0ff3SThierry Escande 
437*204bddcbSThierry Escande 	nfcsim_device_free(dev0);
438*204bddcbSThierry Escande 	nfcsim_device_free(dev1);
439*204bddcbSThierry Escande 
440*204bddcbSThierry Escande 	nfcsim_link_free(link0);
441*204bddcbSThierry Escande 	nfcsim_link_free(link1);
4427cbe0ff3SThierry Escande }
4437cbe0ff3SThierry Escande 
4447cbe0ff3SThierry Escande module_init(nfcsim_init);
4457cbe0ff3SThierry Escande module_exit(nfcsim_exit);
4467cbe0ff3SThierry Escande 
4477cbe0ff3SThierry Escande MODULE_DESCRIPTION("NFCSim driver ver " NFCSIM_VERSION);
4487cbe0ff3SThierry Escande MODULE_VERSION(NFCSIM_VERSION);
4497cbe0ff3SThierry Escande MODULE_LICENSE("GPL");
450