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