xref: /OK3568_Linux_fs/kernel/net/nfc/core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2011 Instituto Nokia de Tecnologia
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Authors:
6*4882a593Smuzhiyun  *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
7*4882a593Smuzhiyun  *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/rfkill.h>
17*4882a593Smuzhiyun #include <linux/nfc.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <net/genetlink.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include "nfc.h"
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define VERSION "0.1"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define NFC_CHECK_PRES_FREQ_MS	2000
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun int nfc_devlist_generation;
28*4882a593Smuzhiyun DEFINE_MUTEX(nfc_devlist_mutex);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* NFC device ID bitmap */
31*4882a593Smuzhiyun static DEFINE_IDA(nfc_index_ida);
32*4882a593Smuzhiyun 
nfc_fw_download(struct nfc_dev * dev,const char * firmware_name)33*4882a593Smuzhiyun int nfc_fw_download(struct nfc_dev *dev, const char *firmware_name)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	int rc = 0;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	pr_debug("%s do firmware %s\n", dev_name(&dev->dev), firmware_name);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	device_lock(&dev->dev);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	if (dev->shutting_down) {
42*4882a593Smuzhiyun 		rc = -ENODEV;
43*4882a593Smuzhiyun 		goto error;
44*4882a593Smuzhiyun 	}
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (dev->dev_up) {
47*4882a593Smuzhiyun 		rc = -EBUSY;
48*4882a593Smuzhiyun 		goto error;
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	if (!dev->ops->fw_download) {
52*4882a593Smuzhiyun 		rc = -EOPNOTSUPP;
53*4882a593Smuzhiyun 		goto error;
54*4882a593Smuzhiyun 	}
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	dev->fw_download_in_progress = true;
57*4882a593Smuzhiyun 	rc = dev->ops->fw_download(dev, firmware_name);
58*4882a593Smuzhiyun 	if (rc)
59*4882a593Smuzhiyun 		dev->fw_download_in_progress = false;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun error:
62*4882a593Smuzhiyun 	device_unlock(&dev->dev);
63*4882a593Smuzhiyun 	return rc;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /**
67*4882a593Smuzhiyun  * nfc_fw_download_done - inform that a firmware download was completed
68*4882a593Smuzhiyun  *
69*4882a593Smuzhiyun  * @dev: The nfc device to which firmware was downloaded
70*4882a593Smuzhiyun  * @firmware_name: The firmware filename
71*4882a593Smuzhiyun  * @result: The positive value of a standard errno value
72*4882a593Smuzhiyun  */
nfc_fw_download_done(struct nfc_dev * dev,const char * firmware_name,u32 result)73*4882a593Smuzhiyun int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
74*4882a593Smuzhiyun 			 u32 result)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	dev->fw_download_in_progress = false;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	return nfc_genl_fw_download_done(dev, firmware_name, result);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_fw_download_done);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun /**
83*4882a593Smuzhiyun  * nfc_dev_up - turn on the NFC device
84*4882a593Smuzhiyun  *
85*4882a593Smuzhiyun  * @dev: The nfc device to be turned on
86*4882a593Smuzhiyun  *
87*4882a593Smuzhiyun  * The device remains up until the nfc_dev_down function is called.
88*4882a593Smuzhiyun  */
nfc_dev_up(struct nfc_dev * dev)89*4882a593Smuzhiyun int nfc_dev_up(struct nfc_dev *dev)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	int rc = 0;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	device_lock(&dev->dev);
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	if (dev->shutting_down) {
98*4882a593Smuzhiyun 		rc = -ENODEV;
99*4882a593Smuzhiyun 		goto error;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
103*4882a593Smuzhiyun 		rc = -ERFKILL;
104*4882a593Smuzhiyun 		goto error;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (dev->fw_download_in_progress) {
108*4882a593Smuzhiyun 		rc = -EBUSY;
109*4882a593Smuzhiyun 		goto error;
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	if (dev->dev_up) {
113*4882a593Smuzhiyun 		rc = -EALREADY;
114*4882a593Smuzhiyun 		goto error;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	if (dev->ops->dev_up)
118*4882a593Smuzhiyun 		rc = dev->ops->dev_up(dev);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	if (!rc)
121*4882a593Smuzhiyun 		dev->dev_up = true;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	/* We have to enable the device before discovering SEs */
124*4882a593Smuzhiyun 	if (dev->ops->discover_se && dev->ops->discover_se(dev))
125*4882a593Smuzhiyun 		pr_err("SE discovery failed\n");
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun error:
128*4882a593Smuzhiyun 	device_unlock(&dev->dev);
129*4882a593Smuzhiyun 	return rc;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun /**
133*4882a593Smuzhiyun  * nfc_dev_down - turn off the NFC device
134*4882a593Smuzhiyun  *
135*4882a593Smuzhiyun  * @dev: The nfc device to be turned off
136*4882a593Smuzhiyun  */
nfc_dev_down(struct nfc_dev * dev)137*4882a593Smuzhiyun int nfc_dev_down(struct nfc_dev *dev)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	int rc = 0;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	device_lock(&dev->dev);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	if (dev->shutting_down) {
146*4882a593Smuzhiyun 		rc = -ENODEV;
147*4882a593Smuzhiyun 		goto error;
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	if (!dev->dev_up) {
151*4882a593Smuzhiyun 		rc = -EALREADY;
152*4882a593Smuzhiyun 		goto error;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	if (dev->polling || dev->active_target) {
156*4882a593Smuzhiyun 		rc = -EBUSY;
157*4882a593Smuzhiyun 		goto error;
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	if (dev->ops->dev_down)
161*4882a593Smuzhiyun 		dev->ops->dev_down(dev);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	dev->dev_up = false;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun error:
166*4882a593Smuzhiyun 	device_unlock(&dev->dev);
167*4882a593Smuzhiyun 	return rc;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
nfc_rfkill_set_block(void * data,bool blocked)170*4882a593Smuzhiyun static int nfc_rfkill_set_block(void *data, bool blocked)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	struct nfc_dev *dev = data;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	pr_debug("%s blocked %d", dev_name(&dev->dev), blocked);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	if (!blocked)
177*4882a593Smuzhiyun 		return 0;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	nfc_dev_down(dev);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	return 0;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static const struct rfkill_ops nfc_rfkill_ops = {
185*4882a593Smuzhiyun 	.set_block = nfc_rfkill_set_block,
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun /**
189*4882a593Smuzhiyun  * nfc_start_poll - start polling for nfc targets
190*4882a593Smuzhiyun  *
191*4882a593Smuzhiyun  * @dev: The nfc device that must start polling
192*4882a593Smuzhiyun  * @protocols: bitset of nfc protocols that must be used for polling
193*4882a593Smuzhiyun  *
194*4882a593Smuzhiyun  * The device remains polling for targets until a target is found or
195*4882a593Smuzhiyun  * the nfc_stop_poll function is called.
196*4882a593Smuzhiyun  */
nfc_start_poll(struct nfc_dev * dev,u32 im_protocols,u32 tm_protocols)197*4882a593Smuzhiyun int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	int rc;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n",
202*4882a593Smuzhiyun 		 dev_name(&dev->dev), im_protocols, tm_protocols);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	if (!im_protocols && !tm_protocols)
205*4882a593Smuzhiyun 		return -EINVAL;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	device_lock(&dev->dev);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (dev->shutting_down) {
210*4882a593Smuzhiyun 		rc = -ENODEV;
211*4882a593Smuzhiyun 		goto error;
212*4882a593Smuzhiyun 	}
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if (!dev->dev_up) {
215*4882a593Smuzhiyun 		rc = -ENODEV;
216*4882a593Smuzhiyun 		goto error;
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	if (dev->polling) {
220*4882a593Smuzhiyun 		rc = -EBUSY;
221*4882a593Smuzhiyun 		goto error;
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	rc = dev->ops->start_poll(dev, im_protocols, tm_protocols);
225*4882a593Smuzhiyun 	if (!rc) {
226*4882a593Smuzhiyun 		dev->polling = true;
227*4882a593Smuzhiyun 		dev->rf_mode = NFC_RF_NONE;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun error:
231*4882a593Smuzhiyun 	device_unlock(&dev->dev);
232*4882a593Smuzhiyun 	return rc;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun /**
236*4882a593Smuzhiyun  * nfc_stop_poll - stop polling for nfc targets
237*4882a593Smuzhiyun  *
238*4882a593Smuzhiyun  * @dev: The nfc device that must stop polling
239*4882a593Smuzhiyun  */
nfc_stop_poll(struct nfc_dev * dev)240*4882a593Smuzhiyun int nfc_stop_poll(struct nfc_dev *dev)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	int rc = 0;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	device_lock(&dev->dev);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (dev->shutting_down) {
249*4882a593Smuzhiyun 		rc = -ENODEV;
250*4882a593Smuzhiyun 		goto error;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	if (!dev->polling) {
254*4882a593Smuzhiyun 		rc = -EINVAL;
255*4882a593Smuzhiyun 		goto error;
256*4882a593Smuzhiyun 	}
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	dev->ops->stop_poll(dev);
259*4882a593Smuzhiyun 	dev->polling = false;
260*4882a593Smuzhiyun 	dev->rf_mode = NFC_RF_NONE;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun error:
263*4882a593Smuzhiyun 	device_unlock(&dev->dev);
264*4882a593Smuzhiyun 	return rc;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
nfc_find_target(struct nfc_dev * dev,u32 target_idx)267*4882a593Smuzhiyun static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	int i;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	for (i = 0; i < dev->n_targets; i++) {
272*4882a593Smuzhiyun 		if (dev->targets[i].idx == target_idx)
273*4882a593Smuzhiyun 			return &dev->targets[i];
274*4882a593Smuzhiyun 	}
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	return NULL;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
nfc_dep_link_up(struct nfc_dev * dev,int target_index,u8 comm_mode)279*4882a593Smuzhiyun int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	int rc = 0;
282*4882a593Smuzhiyun 	u8 *gb;
283*4882a593Smuzhiyun 	size_t gb_len;
284*4882a593Smuzhiyun 	struct nfc_target *target;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (!dev->ops->dep_link_up)
289*4882a593Smuzhiyun 		return -EOPNOTSUPP;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	device_lock(&dev->dev);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (dev->shutting_down) {
294*4882a593Smuzhiyun 		rc = -ENODEV;
295*4882a593Smuzhiyun 		goto error;
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	if (dev->dep_link_up == true) {
299*4882a593Smuzhiyun 		rc = -EALREADY;
300*4882a593Smuzhiyun 		goto error;
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	gb = nfc_llcp_general_bytes(dev, &gb_len);
304*4882a593Smuzhiyun 	if (gb_len > NFC_MAX_GT_LEN) {
305*4882a593Smuzhiyun 		rc = -EINVAL;
306*4882a593Smuzhiyun 		goto error;
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	target = nfc_find_target(dev, target_index);
310*4882a593Smuzhiyun 	if (target == NULL) {
311*4882a593Smuzhiyun 		rc = -ENOTCONN;
312*4882a593Smuzhiyun 		goto error;
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len);
316*4882a593Smuzhiyun 	if (!rc) {
317*4882a593Smuzhiyun 		dev->active_target = target;
318*4882a593Smuzhiyun 		dev->rf_mode = NFC_RF_INITIATOR;
319*4882a593Smuzhiyun 	}
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun error:
322*4882a593Smuzhiyun 	device_unlock(&dev->dev);
323*4882a593Smuzhiyun 	return rc;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
nfc_dep_link_down(struct nfc_dev * dev)326*4882a593Smuzhiyun int nfc_dep_link_down(struct nfc_dev *dev)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	int rc = 0;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	if (!dev->ops->dep_link_down)
333*4882a593Smuzhiyun 		return -EOPNOTSUPP;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	device_lock(&dev->dev);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (dev->shutting_down) {
338*4882a593Smuzhiyun 		rc = -ENODEV;
339*4882a593Smuzhiyun 		goto error;
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	if (dev->dep_link_up == false) {
343*4882a593Smuzhiyun 		rc = -EALREADY;
344*4882a593Smuzhiyun 		goto error;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	rc = dev->ops->dep_link_down(dev);
348*4882a593Smuzhiyun 	if (!rc) {
349*4882a593Smuzhiyun 		dev->dep_link_up = false;
350*4882a593Smuzhiyun 		dev->active_target = NULL;
351*4882a593Smuzhiyun 		dev->rf_mode = NFC_RF_NONE;
352*4882a593Smuzhiyun 		nfc_llcp_mac_is_down(dev);
353*4882a593Smuzhiyun 		nfc_genl_dep_link_down_event(dev);
354*4882a593Smuzhiyun 	}
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun error:
357*4882a593Smuzhiyun 	device_unlock(&dev->dev);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	return rc;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
nfc_dep_link_is_up(struct nfc_dev * dev,u32 target_idx,u8 comm_mode,u8 rf_mode)362*4882a593Smuzhiyun int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
363*4882a593Smuzhiyun 		       u8 comm_mode, u8 rf_mode)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	dev->dep_link_up = true;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	if (!dev->active_target && rf_mode == NFC_RF_INITIATOR) {
368*4882a593Smuzhiyun 		struct nfc_target *target;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 		target = nfc_find_target(dev, target_idx);
371*4882a593Smuzhiyun 		if (target == NULL)
372*4882a593Smuzhiyun 			return -ENOTCONN;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 		dev->active_target = target;
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	dev->polling = false;
378*4882a593Smuzhiyun 	dev->rf_mode = rf_mode;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode);
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_dep_link_is_up);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun /**
387*4882a593Smuzhiyun  * nfc_activate_target - prepare the target for data exchange
388*4882a593Smuzhiyun  *
389*4882a593Smuzhiyun  * @dev: The nfc device that found the target
390*4882a593Smuzhiyun  * @target_idx: index of the target that must be activated
391*4882a593Smuzhiyun  * @protocol: nfc protocol that will be used for data exchange
392*4882a593Smuzhiyun  */
nfc_activate_target(struct nfc_dev * dev,u32 target_idx,u32 protocol)393*4882a593Smuzhiyun int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	int rc;
396*4882a593Smuzhiyun 	struct nfc_target *target;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	pr_debug("dev_name=%s target_idx=%u protocol=%u\n",
399*4882a593Smuzhiyun 		 dev_name(&dev->dev), target_idx, protocol);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	device_lock(&dev->dev);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	if (dev->shutting_down) {
404*4882a593Smuzhiyun 		rc = -ENODEV;
405*4882a593Smuzhiyun 		goto error;
406*4882a593Smuzhiyun 	}
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	if (dev->active_target) {
409*4882a593Smuzhiyun 		rc = -EBUSY;
410*4882a593Smuzhiyun 		goto error;
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	target = nfc_find_target(dev, target_idx);
414*4882a593Smuzhiyun 	if (target == NULL) {
415*4882a593Smuzhiyun 		rc = -ENOTCONN;
416*4882a593Smuzhiyun 		goto error;
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	rc = dev->ops->activate_target(dev, target, protocol);
420*4882a593Smuzhiyun 	if (!rc) {
421*4882a593Smuzhiyun 		dev->active_target = target;
422*4882a593Smuzhiyun 		dev->rf_mode = NFC_RF_INITIATOR;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 		if (dev->ops->check_presence && !dev->shutting_down)
425*4882a593Smuzhiyun 			mod_timer(&dev->check_pres_timer, jiffies +
426*4882a593Smuzhiyun 				  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun error:
430*4882a593Smuzhiyun 	device_unlock(&dev->dev);
431*4882a593Smuzhiyun 	return rc;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun /**
435*4882a593Smuzhiyun  * nfc_deactivate_target - deactivate a nfc target
436*4882a593Smuzhiyun  *
437*4882a593Smuzhiyun  * @dev: The nfc device that found the target
438*4882a593Smuzhiyun  * @target_idx: index of the target that must be deactivated
439*4882a593Smuzhiyun  */
nfc_deactivate_target(struct nfc_dev * dev,u32 target_idx,u8 mode)440*4882a593Smuzhiyun int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx, u8 mode)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	int rc = 0;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	pr_debug("dev_name=%s target_idx=%u\n",
445*4882a593Smuzhiyun 		 dev_name(&dev->dev), target_idx);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	device_lock(&dev->dev);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	if (dev->shutting_down) {
450*4882a593Smuzhiyun 		rc = -ENODEV;
451*4882a593Smuzhiyun 		goto error;
452*4882a593Smuzhiyun 	}
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	if (dev->active_target == NULL) {
455*4882a593Smuzhiyun 		rc = -ENOTCONN;
456*4882a593Smuzhiyun 		goto error;
457*4882a593Smuzhiyun 	}
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	if (dev->active_target->idx != target_idx) {
460*4882a593Smuzhiyun 		rc = -ENOTCONN;
461*4882a593Smuzhiyun 		goto error;
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (dev->ops->check_presence)
465*4882a593Smuzhiyun 		del_timer_sync(&dev->check_pres_timer);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	dev->ops->deactivate_target(dev, dev->active_target, mode);
468*4882a593Smuzhiyun 	dev->active_target = NULL;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun error:
471*4882a593Smuzhiyun 	device_unlock(&dev->dev);
472*4882a593Smuzhiyun 	return rc;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun /**
476*4882a593Smuzhiyun  * nfc_data_exchange - transceive data
477*4882a593Smuzhiyun  *
478*4882a593Smuzhiyun  * @dev: The nfc device that found the target
479*4882a593Smuzhiyun  * @target_idx: index of the target
480*4882a593Smuzhiyun  * @skb: data to be sent
481*4882a593Smuzhiyun  * @cb: callback called when the response is received
482*4882a593Smuzhiyun  * @cb_context: parameter for the callback function
483*4882a593Smuzhiyun  *
484*4882a593Smuzhiyun  * The user must wait for the callback before calling this function again.
485*4882a593Smuzhiyun  */
nfc_data_exchange(struct nfc_dev * dev,u32 target_idx,struct sk_buff * skb,data_exchange_cb_t cb,void * cb_context)486*4882a593Smuzhiyun int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
487*4882a593Smuzhiyun 		      data_exchange_cb_t cb, void *cb_context)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	int rc;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	pr_debug("dev_name=%s target_idx=%u skb->len=%u\n",
492*4882a593Smuzhiyun 		 dev_name(&dev->dev), target_idx, skb->len);
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	device_lock(&dev->dev);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	if (dev->shutting_down) {
497*4882a593Smuzhiyun 		rc = -ENODEV;
498*4882a593Smuzhiyun 		kfree_skb(skb);
499*4882a593Smuzhiyun 		goto error;
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) {
503*4882a593Smuzhiyun 		if (dev->active_target->idx != target_idx) {
504*4882a593Smuzhiyun 			rc = -EADDRNOTAVAIL;
505*4882a593Smuzhiyun 			kfree_skb(skb);
506*4882a593Smuzhiyun 			goto error;
507*4882a593Smuzhiyun 		}
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 		if (dev->ops->check_presence)
510*4882a593Smuzhiyun 			del_timer_sync(&dev->check_pres_timer);
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 		rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb,
513*4882a593Smuzhiyun 					     cb_context);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 		if (!rc && dev->ops->check_presence && !dev->shutting_down)
516*4882a593Smuzhiyun 			mod_timer(&dev->check_pres_timer, jiffies +
517*4882a593Smuzhiyun 				  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
518*4882a593Smuzhiyun 	} else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) {
519*4882a593Smuzhiyun 		rc = dev->ops->tm_send(dev, skb);
520*4882a593Smuzhiyun 	} else {
521*4882a593Smuzhiyun 		rc = -ENOTCONN;
522*4882a593Smuzhiyun 		kfree_skb(skb);
523*4882a593Smuzhiyun 		goto error;
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun error:
528*4882a593Smuzhiyun 	device_unlock(&dev->dev);
529*4882a593Smuzhiyun 	return rc;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
nfc_find_se(struct nfc_dev * dev,u32 se_idx)532*4882a593Smuzhiyun struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	struct nfc_se *se;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	list_for_each_entry(se, &dev->secure_elements, list)
537*4882a593Smuzhiyun 		if (se->idx == se_idx)
538*4882a593Smuzhiyun 			return se;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	return NULL;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_find_se);
543*4882a593Smuzhiyun 
nfc_enable_se(struct nfc_dev * dev,u32 se_idx)544*4882a593Smuzhiyun int nfc_enable_se(struct nfc_dev *dev, u32 se_idx)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun 	struct nfc_se *se;
547*4882a593Smuzhiyun 	int rc;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	device_lock(&dev->dev);
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	if (dev->shutting_down) {
554*4882a593Smuzhiyun 		rc = -ENODEV;
555*4882a593Smuzhiyun 		goto error;
556*4882a593Smuzhiyun 	}
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	if (!dev->dev_up) {
559*4882a593Smuzhiyun 		rc = -ENODEV;
560*4882a593Smuzhiyun 		goto error;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	if (dev->polling) {
564*4882a593Smuzhiyun 		rc = -EBUSY;
565*4882a593Smuzhiyun 		goto error;
566*4882a593Smuzhiyun 	}
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	if (!dev->ops->enable_se || !dev->ops->disable_se) {
569*4882a593Smuzhiyun 		rc = -EOPNOTSUPP;
570*4882a593Smuzhiyun 		goto error;
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	se = nfc_find_se(dev, se_idx);
574*4882a593Smuzhiyun 	if (!se) {
575*4882a593Smuzhiyun 		rc = -EINVAL;
576*4882a593Smuzhiyun 		goto error;
577*4882a593Smuzhiyun 	}
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	if (se->state == NFC_SE_ENABLED) {
580*4882a593Smuzhiyun 		rc = -EALREADY;
581*4882a593Smuzhiyun 		goto error;
582*4882a593Smuzhiyun 	}
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	rc = dev->ops->enable_se(dev, se_idx);
585*4882a593Smuzhiyun 	if (rc >= 0)
586*4882a593Smuzhiyun 		se->state = NFC_SE_ENABLED;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun error:
589*4882a593Smuzhiyun 	device_unlock(&dev->dev);
590*4882a593Smuzhiyun 	return rc;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun 
nfc_disable_se(struct nfc_dev * dev,u32 se_idx)593*4882a593Smuzhiyun int nfc_disable_se(struct nfc_dev *dev, u32 se_idx)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun 	struct nfc_se *se;
596*4882a593Smuzhiyun 	int rc;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	device_lock(&dev->dev);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	if (dev->shutting_down) {
603*4882a593Smuzhiyun 		rc = -ENODEV;
604*4882a593Smuzhiyun 		goto error;
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	if (!dev->dev_up) {
608*4882a593Smuzhiyun 		rc = -ENODEV;
609*4882a593Smuzhiyun 		goto error;
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	if (!dev->ops->enable_se || !dev->ops->disable_se) {
613*4882a593Smuzhiyun 		rc = -EOPNOTSUPP;
614*4882a593Smuzhiyun 		goto error;
615*4882a593Smuzhiyun 	}
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	se = nfc_find_se(dev, se_idx);
618*4882a593Smuzhiyun 	if (!se) {
619*4882a593Smuzhiyun 		rc = -EINVAL;
620*4882a593Smuzhiyun 		goto error;
621*4882a593Smuzhiyun 	}
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (se->state == NFC_SE_DISABLED) {
624*4882a593Smuzhiyun 		rc = -EALREADY;
625*4882a593Smuzhiyun 		goto error;
626*4882a593Smuzhiyun 	}
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	rc = dev->ops->disable_se(dev, se_idx);
629*4882a593Smuzhiyun 	if (rc >= 0)
630*4882a593Smuzhiyun 		se->state = NFC_SE_DISABLED;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun error:
633*4882a593Smuzhiyun 	device_unlock(&dev->dev);
634*4882a593Smuzhiyun 	return rc;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
nfc_set_remote_general_bytes(struct nfc_dev * dev,u8 * gb,u8 gb_len)637*4882a593Smuzhiyun int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len);
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	return nfc_llcp_set_remote_gb(dev, gb, gb_len);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_set_remote_general_bytes);
644*4882a593Smuzhiyun 
nfc_get_local_general_bytes(struct nfc_dev * dev,size_t * gb_len)645*4882a593Smuzhiyun u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	return nfc_llcp_general_bytes(dev, gb_len);
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_get_local_general_bytes);
652*4882a593Smuzhiyun 
nfc_tm_data_received(struct nfc_dev * dev,struct sk_buff * skb)653*4882a593Smuzhiyun int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun 	/* Only LLCP target mode for now */
656*4882a593Smuzhiyun 	if (dev->dep_link_up == false) {
657*4882a593Smuzhiyun 		kfree_skb(skb);
658*4882a593Smuzhiyun 		return -ENOLINK;
659*4882a593Smuzhiyun 	}
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	return nfc_llcp_data_received(dev, skb);
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_tm_data_received);
664*4882a593Smuzhiyun 
nfc_tm_activated(struct nfc_dev * dev,u32 protocol,u8 comm_mode,u8 * gb,size_t gb_len)665*4882a593Smuzhiyun int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
666*4882a593Smuzhiyun 		     u8 *gb, size_t gb_len)
667*4882a593Smuzhiyun {
668*4882a593Smuzhiyun 	int rc;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	device_lock(&dev->dev);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	dev->polling = false;
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	if (gb != NULL) {
675*4882a593Smuzhiyun 		rc = nfc_set_remote_general_bytes(dev, gb, gb_len);
676*4882a593Smuzhiyun 		if (rc < 0)
677*4882a593Smuzhiyun 			goto out;
678*4882a593Smuzhiyun 	}
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	dev->rf_mode = NFC_RF_TARGET;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	if (protocol == NFC_PROTO_NFC_DEP_MASK)
683*4882a593Smuzhiyun 		nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET);
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	rc = nfc_genl_tm_activated(dev, protocol);
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun out:
688*4882a593Smuzhiyun 	device_unlock(&dev->dev);
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	return rc;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_tm_activated);
693*4882a593Smuzhiyun 
nfc_tm_deactivated(struct nfc_dev * dev)694*4882a593Smuzhiyun int nfc_tm_deactivated(struct nfc_dev *dev)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun 	dev->dep_link_up = false;
697*4882a593Smuzhiyun 	dev->rf_mode = NFC_RF_NONE;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	return nfc_genl_tm_deactivated(dev);
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_tm_deactivated);
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun /**
704*4882a593Smuzhiyun  * nfc_alloc_send_skb - allocate a skb for data exchange responses
705*4882a593Smuzhiyun  *
706*4882a593Smuzhiyun  * @size: size to allocate
707*4882a593Smuzhiyun  */
nfc_alloc_send_skb(struct nfc_dev * dev,struct sock * sk,unsigned int flags,unsigned int size,unsigned int * err)708*4882a593Smuzhiyun struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
709*4882a593Smuzhiyun 				   unsigned int flags, unsigned int size,
710*4882a593Smuzhiyun 				   unsigned int *err)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun 	struct sk_buff *skb;
713*4882a593Smuzhiyun 	unsigned int total_size;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	total_size = size +
716*4882a593Smuzhiyun 		dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	skb = sock_alloc_send_skb(sk, total_size, flags & MSG_DONTWAIT, err);
719*4882a593Smuzhiyun 	if (skb)
720*4882a593Smuzhiyun 		skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	return skb;
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun /**
726*4882a593Smuzhiyun  * nfc_alloc_recv_skb - allocate a skb for data exchange responses
727*4882a593Smuzhiyun  *
728*4882a593Smuzhiyun  * @size: size to allocate
729*4882a593Smuzhiyun  * @gfp: gfp flags
730*4882a593Smuzhiyun  */
nfc_alloc_recv_skb(unsigned int size,gfp_t gfp)731*4882a593Smuzhiyun struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	struct sk_buff *skb;
734*4882a593Smuzhiyun 	unsigned int total_size;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	total_size = size + 1;
737*4882a593Smuzhiyun 	skb = alloc_skb(total_size, gfp);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	if (skb)
740*4882a593Smuzhiyun 		skb_reserve(skb, 1);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	return skb;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_alloc_recv_skb);
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun /**
747*4882a593Smuzhiyun  * nfc_targets_found - inform that targets were found
748*4882a593Smuzhiyun  *
749*4882a593Smuzhiyun  * @dev: The nfc device that found the targets
750*4882a593Smuzhiyun  * @targets: array of nfc targets found
751*4882a593Smuzhiyun  * @n_targets: targets array size
752*4882a593Smuzhiyun  *
753*4882a593Smuzhiyun  * The device driver must call this function when one or many nfc targets
754*4882a593Smuzhiyun  * are found. After calling this function, the device driver must stop
755*4882a593Smuzhiyun  * polling for targets.
756*4882a593Smuzhiyun  * NOTE: This function can be called with targets=NULL and n_targets=0 to
757*4882a593Smuzhiyun  * notify a driver error, meaning that the polling operation cannot complete.
758*4882a593Smuzhiyun  * IMPORTANT: this function must not be called from an atomic context.
759*4882a593Smuzhiyun  * In addition, it must also not be called from a context that would prevent
760*4882a593Smuzhiyun  * the NFC Core to call other nfc ops entry point concurrently.
761*4882a593Smuzhiyun  */
nfc_targets_found(struct nfc_dev * dev,struct nfc_target * targets,int n_targets)762*4882a593Smuzhiyun int nfc_targets_found(struct nfc_dev *dev,
763*4882a593Smuzhiyun 		      struct nfc_target *targets, int n_targets)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun 	int i;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	for (i = 0; i < n_targets; i++)
770*4882a593Smuzhiyun 		targets[i].idx = dev->target_next_idx++;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	device_lock(&dev->dev);
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	if (dev->polling == false) {
775*4882a593Smuzhiyun 		device_unlock(&dev->dev);
776*4882a593Smuzhiyun 		return 0;
777*4882a593Smuzhiyun 	}
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	dev->polling = false;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	dev->targets_generation++;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	kfree(dev->targets);
784*4882a593Smuzhiyun 	dev->targets = NULL;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	if (targets) {
787*4882a593Smuzhiyun 		dev->targets = kmemdup(targets,
788*4882a593Smuzhiyun 				       n_targets * sizeof(struct nfc_target),
789*4882a593Smuzhiyun 				       GFP_ATOMIC);
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 		if (!dev->targets) {
792*4882a593Smuzhiyun 			dev->n_targets = 0;
793*4882a593Smuzhiyun 			device_unlock(&dev->dev);
794*4882a593Smuzhiyun 			return -ENOMEM;
795*4882a593Smuzhiyun 		}
796*4882a593Smuzhiyun 	}
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	dev->n_targets = n_targets;
799*4882a593Smuzhiyun 	device_unlock(&dev->dev);
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	nfc_genl_targets_found(dev);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	return 0;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_targets_found);
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun /**
808*4882a593Smuzhiyun  * nfc_target_lost - inform that an activated target went out of field
809*4882a593Smuzhiyun  *
810*4882a593Smuzhiyun  * @dev: The nfc device that had the activated target in field
811*4882a593Smuzhiyun  * @target_idx: the nfc index of the target
812*4882a593Smuzhiyun  *
813*4882a593Smuzhiyun  * The device driver must call this function when the activated target
814*4882a593Smuzhiyun  * goes out of the field.
815*4882a593Smuzhiyun  * IMPORTANT: this function must not be called from an atomic context.
816*4882a593Smuzhiyun  * In addition, it must also not be called from a context that would prevent
817*4882a593Smuzhiyun  * the NFC Core to call other nfc ops entry point concurrently.
818*4882a593Smuzhiyun  */
nfc_target_lost(struct nfc_dev * dev,u32 target_idx)819*4882a593Smuzhiyun int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun 	struct nfc_target *tg;
822*4882a593Smuzhiyun 	int i;
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 	pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx);
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	device_lock(&dev->dev);
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	for (i = 0; i < dev->n_targets; i++) {
829*4882a593Smuzhiyun 		tg = &dev->targets[i];
830*4882a593Smuzhiyun 		if (tg->idx == target_idx)
831*4882a593Smuzhiyun 			break;
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	if (i == dev->n_targets) {
835*4882a593Smuzhiyun 		device_unlock(&dev->dev);
836*4882a593Smuzhiyun 		return -EINVAL;
837*4882a593Smuzhiyun 	}
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	dev->targets_generation++;
840*4882a593Smuzhiyun 	dev->n_targets--;
841*4882a593Smuzhiyun 	dev->active_target = NULL;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	if (dev->n_targets) {
844*4882a593Smuzhiyun 		memcpy(&dev->targets[i], &dev->targets[i + 1],
845*4882a593Smuzhiyun 		       (dev->n_targets - i) * sizeof(struct nfc_target));
846*4882a593Smuzhiyun 	} else {
847*4882a593Smuzhiyun 		kfree(dev->targets);
848*4882a593Smuzhiyun 		dev->targets = NULL;
849*4882a593Smuzhiyun 	}
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	device_unlock(&dev->dev);
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	nfc_genl_target_lost(dev, target_idx);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	return 0;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_target_lost);
858*4882a593Smuzhiyun 
nfc_driver_failure(struct nfc_dev * dev,int err)859*4882a593Smuzhiyun inline void nfc_driver_failure(struct nfc_dev *dev, int err)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun 	nfc_targets_found(dev, NULL, 0);
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_driver_failure);
864*4882a593Smuzhiyun 
nfc_add_se(struct nfc_dev * dev,u32 se_idx,u16 type)865*4882a593Smuzhiyun int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type)
866*4882a593Smuzhiyun {
867*4882a593Smuzhiyun 	struct nfc_se *se;
868*4882a593Smuzhiyun 	int rc;
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	se = nfc_find_se(dev, se_idx);
873*4882a593Smuzhiyun 	if (se)
874*4882a593Smuzhiyun 		return -EALREADY;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	se = kzalloc(sizeof(struct nfc_se), GFP_KERNEL);
877*4882a593Smuzhiyun 	if (!se)
878*4882a593Smuzhiyun 		return -ENOMEM;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	se->idx = se_idx;
881*4882a593Smuzhiyun 	se->type = type;
882*4882a593Smuzhiyun 	se->state = NFC_SE_DISABLED;
883*4882a593Smuzhiyun 	INIT_LIST_HEAD(&se->list);
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 	list_add(&se->list, &dev->secure_elements);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	rc = nfc_genl_se_added(dev, se_idx, type);
888*4882a593Smuzhiyun 	if (rc < 0) {
889*4882a593Smuzhiyun 		list_del(&se->list);
890*4882a593Smuzhiyun 		kfree(se);
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 		return rc;
893*4882a593Smuzhiyun 	}
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	return 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_add_se);
898*4882a593Smuzhiyun 
nfc_remove_se(struct nfc_dev * dev,u32 se_idx)899*4882a593Smuzhiyun int nfc_remove_se(struct nfc_dev *dev, u32 se_idx)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun 	struct nfc_se *se, *n;
902*4882a593Smuzhiyun 	int rc;
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	list_for_each_entry_safe(se, n, &dev->secure_elements, list)
907*4882a593Smuzhiyun 		if (se->idx == se_idx) {
908*4882a593Smuzhiyun 			rc = nfc_genl_se_removed(dev, se_idx);
909*4882a593Smuzhiyun 			if (rc < 0)
910*4882a593Smuzhiyun 				return rc;
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 			list_del(&se->list);
913*4882a593Smuzhiyun 			kfree(se);
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 			return 0;
916*4882a593Smuzhiyun 		}
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	return -EINVAL;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_remove_se);
921*4882a593Smuzhiyun 
nfc_se_transaction(struct nfc_dev * dev,u8 se_idx,struct nfc_evt_transaction * evt_transaction)922*4882a593Smuzhiyun int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
923*4882a593Smuzhiyun 		       struct nfc_evt_transaction *evt_transaction)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun 	int rc;
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	pr_debug("transaction: %x\n", se_idx);
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 	device_lock(&dev->dev);
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	if (!evt_transaction) {
932*4882a593Smuzhiyun 		rc = -EPROTO;
933*4882a593Smuzhiyun 		goto out;
934*4882a593Smuzhiyun 	}
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	rc = nfc_genl_se_transaction(dev, se_idx, evt_transaction);
937*4882a593Smuzhiyun out:
938*4882a593Smuzhiyun 	device_unlock(&dev->dev);
939*4882a593Smuzhiyun 	return rc;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_se_transaction);
942*4882a593Smuzhiyun 
nfc_se_connectivity(struct nfc_dev * dev,u8 se_idx)943*4882a593Smuzhiyun int nfc_se_connectivity(struct nfc_dev *dev, u8 se_idx)
944*4882a593Smuzhiyun {
945*4882a593Smuzhiyun 	int rc;
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 	pr_debug("connectivity: %x\n", se_idx);
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	device_lock(&dev->dev);
950*4882a593Smuzhiyun 	rc = nfc_genl_se_connectivity(dev, se_idx);
951*4882a593Smuzhiyun 	device_unlock(&dev->dev);
952*4882a593Smuzhiyun 	return rc;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_se_connectivity);
955*4882a593Smuzhiyun 
nfc_release(struct device * d)956*4882a593Smuzhiyun static void nfc_release(struct device *d)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun 	struct nfc_dev *dev = to_nfc_dev(d);
959*4882a593Smuzhiyun 	struct nfc_se *se, *n;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	nfc_genl_data_exit(&dev->genl_data);
964*4882a593Smuzhiyun 	kfree(dev->targets);
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	list_for_each_entry_safe(se, n, &dev->secure_elements, list) {
967*4882a593Smuzhiyun 			nfc_genl_se_removed(dev, se->idx);
968*4882a593Smuzhiyun 			list_del(&se->list);
969*4882a593Smuzhiyun 			kfree(se);
970*4882a593Smuzhiyun 	}
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	ida_simple_remove(&nfc_index_ida, dev->idx);
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	kfree(dev);
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun 
nfc_check_pres_work(struct work_struct * work)977*4882a593Smuzhiyun static void nfc_check_pres_work(struct work_struct *work)
978*4882a593Smuzhiyun {
979*4882a593Smuzhiyun 	struct nfc_dev *dev = container_of(work, struct nfc_dev,
980*4882a593Smuzhiyun 					   check_pres_work);
981*4882a593Smuzhiyun 	int rc;
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	device_lock(&dev->dev);
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) {
986*4882a593Smuzhiyun 		rc = dev->ops->check_presence(dev, dev->active_target);
987*4882a593Smuzhiyun 		if (rc == -EOPNOTSUPP)
988*4882a593Smuzhiyun 			goto exit;
989*4882a593Smuzhiyun 		if (rc) {
990*4882a593Smuzhiyun 			u32 active_target_idx = dev->active_target->idx;
991*4882a593Smuzhiyun 			device_unlock(&dev->dev);
992*4882a593Smuzhiyun 			nfc_target_lost(dev, active_target_idx);
993*4882a593Smuzhiyun 			return;
994*4882a593Smuzhiyun 		}
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 		if (!dev->shutting_down)
997*4882a593Smuzhiyun 			mod_timer(&dev->check_pres_timer, jiffies +
998*4882a593Smuzhiyun 				  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
999*4882a593Smuzhiyun 	}
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun exit:
1002*4882a593Smuzhiyun 	device_unlock(&dev->dev);
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun 
nfc_check_pres_timeout(struct timer_list * t)1005*4882a593Smuzhiyun static void nfc_check_pres_timeout(struct timer_list *t)
1006*4882a593Smuzhiyun {
1007*4882a593Smuzhiyun 	struct nfc_dev *dev = from_timer(dev, t, check_pres_timer);
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun 	schedule_work(&dev->check_pres_work);
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun struct class nfc_class = {
1013*4882a593Smuzhiyun 	.name = "nfc",
1014*4882a593Smuzhiyun 	.dev_release = nfc_release,
1015*4882a593Smuzhiyun };
1016*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_class);
1017*4882a593Smuzhiyun 
match_idx(struct device * d,const void * data)1018*4882a593Smuzhiyun static int match_idx(struct device *d, const void *data)
1019*4882a593Smuzhiyun {
1020*4882a593Smuzhiyun 	struct nfc_dev *dev = to_nfc_dev(d);
1021*4882a593Smuzhiyun 	const unsigned int *idx = data;
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	return dev->idx == *idx;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
nfc_get_device(unsigned int idx)1026*4882a593Smuzhiyun struct nfc_dev *nfc_get_device(unsigned int idx)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun 	struct device *d;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	d = class_find_device(&nfc_class, NULL, &idx, match_idx);
1031*4882a593Smuzhiyun 	if (!d)
1032*4882a593Smuzhiyun 		return NULL;
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	return to_nfc_dev(d);
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun /**
1038*4882a593Smuzhiyun  * nfc_allocate_device - allocate a new nfc device
1039*4882a593Smuzhiyun  *
1040*4882a593Smuzhiyun  * @ops: device operations
1041*4882a593Smuzhiyun  * @supported_protocols: NFC protocols supported by the device
1042*4882a593Smuzhiyun  */
nfc_allocate_device(struct nfc_ops * ops,u32 supported_protocols,int tx_headroom,int tx_tailroom)1043*4882a593Smuzhiyun struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
1044*4882a593Smuzhiyun 				    u32 supported_protocols,
1045*4882a593Smuzhiyun 				    int tx_headroom, int tx_tailroom)
1046*4882a593Smuzhiyun {
1047*4882a593Smuzhiyun 	struct nfc_dev *dev;
1048*4882a593Smuzhiyun 	int rc;
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 	if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
1051*4882a593Smuzhiyun 	    !ops->deactivate_target || !ops->im_transceive)
1052*4882a593Smuzhiyun 		return NULL;
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun 	if (!supported_protocols)
1055*4882a593Smuzhiyun 		return NULL;
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);
1058*4882a593Smuzhiyun 	if (!dev)
1059*4882a593Smuzhiyun 		return NULL;
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
1062*4882a593Smuzhiyun 	if (rc < 0)
1063*4882a593Smuzhiyun 		goto err_free_dev;
1064*4882a593Smuzhiyun 	dev->idx = rc;
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun 	dev->dev.class = &nfc_class;
1067*4882a593Smuzhiyun 	dev_set_name(&dev->dev, "nfc%d", dev->idx);
1068*4882a593Smuzhiyun 	device_initialize(&dev->dev);
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	dev->ops = ops;
1071*4882a593Smuzhiyun 	dev->supported_protocols = supported_protocols;
1072*4882a593Smuzhiyun 	dev->tx_headroom = tx_headroom;
1073*4882a593Smuzhiyun 	dev->tx_tailroom = tx_tailroom;
1074*4882a593Smuzhiyun 	INIT_LIST_HEAD(&dev->secure_elements);
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 	nfc_genl_data_init(&dev->genl_data);
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	dev->rf_mode = NFC_RF_NONE;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	/* first generation must not be 0 */
1081*4882a593Smuzhiyun 	dev->targets_generation = 1;
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun 	if (ops->check_presence) {
1084*4882a593Smuzhiyun 		timer_setup(&dev->check_pres_timer, nfc_check_pres_timeout, 0);
1085*4882a593Smuzhiyun 		INIT_WORK(&dev->check_pres_work, nfc_check_pres_work);
1086*4882a593Smuzhiyun 	}
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	return dev;
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun err_free_dev:
1091*4882a593Smuzhiyun 	kfree(dev);
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	return NULL;
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_allocate_device);
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun /**
1098*4882a593Smuzhiyun  * nfc_register_device - register a nfc device in the nfc subsystem
1099*4882a593Smuzhiyun  *
1100*4882a593Smuzhiyun  * @dev: The nfc device to register
1101*4882a593Smuzhiyun  */
nfc_register_device(struct nfc_dev * dev)1102*4882a593Smuzhiyun int nfc_register_device(struct nfc_dev *dev)
1103*4882a593Smuzhiyun {
1104*4882a593Smuzhiyun 	int rc;
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun 	mutex_lock(&nfc_devlist_mutex);
1109*4882a593Smuzhiyun 	nfc_devlist_generation++;
1110*4882a593Smuzhiyun 	rc = device_add(&dev->dev);
1111*4882a593Smuzhiyun 	mutex_unlock(&nfc_devlist_mutex);
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 	if (rc < 0)
1114*4882a593Smuzhiyun 		return rc;
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun 	rc = nfc_llcp_register_device(dev);
1117*4882a593Smuzhiyun 	if (rc)
1118*4882a593Smuzhiyun 		pr_err("Could not register llcp device\n");
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	device_lock(&dev->dev);
1121*4882a593Smuzhiyun 	dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
1122*4882a593Smuzhiyun 				   RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
1123*4882a593Smuzhiyun 	if (dev->rfkill) {
1124*4882a593Smuzhiyun 		if (rfkill_register(dev->rfkill) < 0) {
1125*4882a593Smuzhiyun 			rfkill_destroy(dev->rfkill);
1126*4882a593Smuzhiyun 			dev->rfkill = NULL;
1127*4882a593Smuzhiyun 		}
1128*4882a593Smuzhiyun 	}
1129*4882a593Smuzhiyun 	dev->shutting_down = false;
1130*4882a593Smuzhiyun 	device_unlock(&dev->dev);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	rc = nfc_genl_device_added(dev);
1133*4882a593Smuzhiyun 	if (rc)
1134*4882a593Smuzhiyun 		pr_debug("The userspace won't be notified that the device %s was added\n",
1135*4882a593Smuzhiyun 			 dev_name(&dev->dev));
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun 	return 0;
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_register_device);
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun /**
1142*4882a593Smuzhiyun  * nfc_unregister_device - unregister a nfc device in the nfc subsystem
1143*4882a593Smuzhiyun  *
1144*4882a593Smuzhiyun  * @dev: The nfc device to unregister
1145*4882a593Smuzhiyun  */
nfc_unregister_device(struct nfc_dev * dev)1146*4882a593Smuzhiyun void nfc_unregister_device(struct nfc_dev *dev)
1147*4882a593Smuzhiyun {
1148*4882a593Smuzhiyun 	int rc;
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	rc = nfc_genl_device_removed(dev);
1153*4882a593Smuzhiyun 	if (rc)
1154*4882a593Smuzhiyun 		pr_debug("The userspace won't be notified that the device %s "
1155*4882a593Smuzhiyun 			 "was removed\n", dev_name(&dev->dev));
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 	device_lock(&dev->dev);
1158*4882a593Smuzhiyun 	if (dev->rfkill) {
1159*4882a593Smuzhiyun 		rfkill_unregister(dev->rfkill);
1160*4882a593Smuzhiyun 		rfkill_destroy(dev->rfkill);
1161*4882a593Smuzhiyun 		dev->rfkill = NULL;
1162*4882a593Smuzhiyun 	}
1163*4882a593Smuzhiyun 	dev->shutting_down = true;
1164*4882a593Smuzhiyun 	device_unlock(&dev->dev);
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	if (dev->ops->check_presence) {
1167*4882a593Smuzhiyun 		del_timer_sync(&dev->check_pres_timer);
1168*4882a593Smuzhiyun 		cancel_work_sync(&dev->check_pres_work);
1169*4882a593Smuzhiyun 	}
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun 	nfc_llcp_unregister_device(dev);
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	mutex_lock(&nfc_devlist_mutex);
1174*4882a593Smuzhiyun 	nfc_devlist_generation++;
1175*4882a593Smuzhiyun 	device_del(&dev->dev);
1176*4882a593Smuzhiyun 	mutex_unlock(&nfc_devlist_mutex);
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun EXPORT_SYMBOL(nfc_unregister_device);
1179*4882a593Smuzhiyun 
nfc_init(void)1180*4882a593Smuzhiyun static int __init nfc_init(void)
1181*4882a593Smuzhiyun {
1182*4882a593Smuzhiyun 	int rc;
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	pr_info("NFC Core ver %s\n", VERSION);
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun 	rc = class_register(&nfc_class);
1187*4882a593Smuzhiyun 	if (rc)
1188*4882a593Smuzhiyun 		return rc;
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun 	rc = nfc_genl_init();
1191*4882a593Smuzhiyun 	if (rc)
1192*4882a593Smuzhiyun 		goto err_genl;
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	/* the first generation must not be 0 */
1195*4882a593Smuzhiyun 	nfc_devlist_generation = 1;
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun 	rc = rawsock_init();
1198*4882a593Smuzhiyun 	if (rc)
1199*4882a593Smuzhiyun 		goto err_rawsock;
1200*4882a593Smuzhiyun 
1201*4882a593Smuzhiyun 	rc = nfc_llcp_init();
1202*4882a593Smuzhiyun 	if (rc)
1203*4882a593Smuzhiyun 		goto err_llcp_sock;
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	rc = af_nfc_init();
1206*4882a593Smuzhiyun 	if (rc)
1207*4882a593Smuzhiyun 		goto err_af_nfc;
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun 	return 0;
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun err_af_nfc:
1212*4882a593Smuzhiyun 	nfc_llcp_exit();
1213*4882a593Smuzhiyun err_llcp_sock:
1214*4882a593Smuzhiyun 	rawsock_exit();
1215*4882a593Smuzhiyun err_rawsock:
1216*4882a593Smuzhiyun 	nfc_genl_exit();
1217*4882a593Smuzhiyun err_genl:
1218*4882a593Smuzhiyun 	class_unregister(&nfc_class);
1219*4882a593Smuzhiyun 	return rc;
1220*4882a593Smuzhiyun }
1221*4882a593Smuzhiyun 
nfc_exit(void)1222*4882a593Smuzhiyun static void __exit nfc_exit(void)
1223*4882a593Smuzhiyun {
1224*4882a593Smuzhiyun 	af_nfc_exit();
1225*4882a593Smuzhiyun 	nfc_llcp_exit();
1226*4882a593Smuzhiyun 	rawsock_exit();
1227*4882a593Smuzhiyun 	nfc_genl_exit();
1228*4882a593Smuzhiyun 	class_unregister(&nfc_class);
1229*4882a593Smuzhiyun }
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun subsys_initcall(nfc_init);
1232*4882a593Smuzhiyun module_exit(nfc_exit);
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
1235*4882a593Smuzhiyun MODULE_DESCRIPTION("NFC Core ver " VERSION);
1236*4882a593Smuzhiyun MODULE_VERSION(VERSION);
1237*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1238*4882a593Smuzhiyun MODULE_ALIAS_NETPROTO(PF_NFC);
1239*4882a593Smuzhiyun MODULE_ALIAS_GENL_FAMILY(NFC_GENL_NAME);
1240