aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorLauro Ramos Venancio <lauro.venancio@openbossa.org>2011-07-01 18:31:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-05 15:26:57 -0400
commit3e256b8f8dfa309a80b5dece388d85d9a9801a29 (patch)
treed5936ec25998426c2166dbd954b0fd8cc32c56af /net/nfc
parent2b4562dfd6ad3579951de21168cb9d266ed3f1bd (diff)
NFC: add nfc subsystem core
The NFC subsystem core is responsible for providing the device driver interface. It is also responsible for providing an interface to the control operations and data exchange. Signed-off-by: Lauro Ramos Venancio <lauro.venancio@openbossa.org> Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/Kconfig16
-rw-r--r--net/nfc/Makefile7
-rw-r--r--net/nfc/core.c365
-rw-r--r--net/nfc/nfc.h78
4 files changed, 466 insertions, 0 deletions
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
new file mode 100644
index 000000000000..33e095b124b3
--- /dev/null
+++ b/net/nfc/Kconfig
@@ -0,0 +1,16 @@
1#
2# NFC sybsystem configuration
3#
4
5menuconfig NFC
6 depends on NET && EXPERIMENTAL
7 tristate "NFC subsystem support (EXPERIMENTAL)"
8 default n
9 help
10 Say Y here if you want to build support for NFC (Near field
11 communication) devices.
12
13 To compile this support as a module, choose M here: the module will
14 be called nfc.
15
16source "drivers/nfc/Kconfig"
diff --git a/net/nfc/Makefile b/net/nfc/Makefile
new file mode 100644
index 000000000000..28bee5958687
--- /dev/null
+++ b/net/nfc/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the Linux NFC subsystem.
3#
4
5obj-$(CONFIG_NFC) += nfc.o
6
7nfc-objs := core.o
diff --git a/net/nfc/core.c b/net/nfc/core.c
new file mode 100644
index 000000000000..19f8035a1ba9
--- /dev/null
+++ b/net/nfc/core.c
@@ -0,0 +1,365 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
6 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/init.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/slab.h>
28
29#include "nfc.h"
30
31#define VERSION "0.1"
32
33int nfc_devlist_generation;
34DEFINE_MUTEX(nfc_devlist_mutex);
35
36int nfc_printk(const char *level, const char *format, ...)
37{
38 struct va_format vaf;
39 va_list args;
40 int r;
41
42 va_start(args, format);
43
44 vaf.fmt = format;
45 vaf.va = &args;
46
47 r = printk("%sNFC: %pV\n", level, &vaf);
48
49 va_end(args);
50
51 return r;
52}
53EXPORT_SYMBOL(nfc_printk);
54
55/**
56 * nfc_start_poll - start polling for nfc targets
57 *
58 * @dev: The nfc device that must start polling
59 * @protocols: bitset of nfc protocols that must be used for polling
60 *
61 * The device remains polling for targets until a target is found or
62 * the nfc_stop_poll function is called.
63 */
64int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
65{
66 int rc;
67
68 nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols);
69
70 if (!protocols)
71 return -EINVAL;
72
73 device_lock(&dev->dev);
74
75 if (!device_is_registered(&dev->dev)) {
76 rc = -ENODEV;
77 goto error;
78 }
79
80 if (dev->polling) {
81 rc = -EBUSY;
82 goto error;
83 }
84
85 rc = dev->ops->start_poll(dev, protocols);
86 if (!rc)
87 dev->polling = true;
88
89error:
90 device_unlock(&dev->dev);
91 return rc;
92}
93
94/**
95 * nfc_stop_poll - stop polling for nfc targets
96 *
97 * @dev: The nfc device that must stop polling
98 */
99int nfc_stop_poll(struct nfc_dev *dev)
100{
101 int rc = 0;
102
103 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
104
105 device_lock(&dev->dev);
106
107 if (!device_is_registered(&dev->dev)) {
108 rc = -ENODEV;
109 goto error;
110 }
111
112 if (!dev->polling) {
113 rc = -EINVAL;
114 goto error;
115 }
116
117 dev->ops->stop_poll(dev);
118 dev->polling = false;
119
120error:
121 device_unlock(&dev->dev);
122 return rc;
123}
124
125/**
126 * nfc_activate_target - prepare the target for data exchange
127 *
128 * @dev: The nfc device that found the target
129 * @target_idx: index of the target that must be activated
130 * @protocol: nfc protocol that will be used for data exchange
131 */
132int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
133{
134 int rc;
135
136 nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev),
137 target_idx, protocol);
138
139 device_lock(&dev->dev);
140
141 if (!device_is_registered(&dev->dev)) {
142 rc = -ENODEV;
143 goto error;
144 }
145
146 rc = dev->ops->activate_target(dev, target_idx, protocol);
147
148error:
149 device_unlock(&dev->dev);
150 return rc;
151}
152
153/**
154 * nfc_deactivate_target - deactivate a nfc target
155 *
156 * @dev: The nfc device that found the target
157 * @target_idx: index of the target that must be deactivated
158 */
159int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
160{
161 int rc = 0;
162
163 nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx);
164
165 device_lock(&dev->dev);
166
167 if (!device_is_registered(&dev->dev)) {
168 rc = -ENODEV;
169 goto error;
170 }
171
172 dev->ops->deactivate_target(dev, target_idx);
173
174error:
175 device_unlock(&dev->dev);
176 return rc;
177}
178
179/**
180 * nfc_data_exchange - transceive data
181 *
182 * @dev: The nfc device that found the target
183 * @target_idx: index of the target
184 * @skb: data to be sent
185 * @cb: callback called when the response is received
186 * @cb_context: parameter for the callback function
187 *
188 * The user must wait for the callback before calling this function again.
189 */
190int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
191 struct sk_buff *skb,
192 data_exchange_cb_t cb,
193 void *cb_context)
194{
195 int rc;
196
197 nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev),
198 target_idx, skb->len);
199
200 device_lock(&dev->dev);
201
202 if (!device_is_registered(&dev->dev)) {
203 rc = -ENODEV;
204 kfree_skb(skb);
205 goto error;
206 }
207
208 rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context);
209
210error:
211 device_unlock(&dev->dev);
212 return rc;
213}
214
215/**
216 * nfc_alloc_skb - allocate a skb for data exchange responses
217 *
218 * @size: size to allocate
219 * @gfp: gfp flags
220 */
221struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
222{
223 struct sk_buff *skb;
224 unsigned int total_size;
225
226 total_size = size + 1;
227 skb = alloc_skb(total_size, gfp);
228
229 if (skb)
230 skb_reserve(skb, 1);
231
232 return skb;
233}
234EXPORT_SYMBOL(nfc_alloc_skb);
235
236static void nfc_release(struct device *d)
237{
238 struct nfc_dev *dev = to_nfc_dev(d);
239
240 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
241
242 kfree(dev);
243}
244
245struct class nfc_class = {
246 .name = "nfc",
247 .dev_release = nfc_release,
248};
249EXPORT_SYMBOL(nfc_class);
250
251static int match_idx(struct device *d, void *data)
252{
253 struct nfc_dev *dev = to_nfc_dev(d);
254 unsigned *idx = data;
255
256 return dev->idx == *idx;
257}
258
259struct nfc_dev *nfc_get_device(unsigned idx)
260{
261 struct device *d;
262
263 d = class_find_device(&nfc_class, NULL, &idx, match_idx);
264 if (!d)
265 return NULL;
266
267 return to_nfc_dev(d);
268}
269
270/**
271 * nfc_allocate_device - allocate a new nfc device
272 *
273 * @ops: device operations
274 * @supported_protocols: NFC protocols supported by the device
275 */
276struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
277 u32 supported_protocols)
278{
279 static atomic_t dev_no = ATOMIC_INIT(0);
280 struct nfc_dev *dev;
281
282 if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
283 !ops->deactivate_target || !ops->data_exchange)
284 return NULL;
285
286 if (!supported_protocols)
287 return NULL;
288
289 dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);
290 if (!dev)
291 return NULL;
292
293 dev->dev.class = &nfc_class;
294 dev->idx = atomic_inc_return(&dev_no) - 1;
295 dev_set_name(&dev->dev, "nfc%d", dev->idx);
296 device_initialize(&dev->dev);
297
298 dev->ops = ops;
299 dev->supported_protocols = supported_protocols;
300
301 return dev;
302}
303EXPORT_SYMBOL(nfc_allocate_device);
304
305/**
306 * nfc_register_device - register a nfc device in the nfc subsystem
307 *
308 * @dev: The nfc device to register
309 */
310int nfc_register_device(struct nfc_dev *dev)
311{
312 int rc;
313
314 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
315
316 mutex_lock(&nfc_devlist_mutex);
317 nfc_devlist_generation++;
318 rc = device_add(&dev->dev);
319 mutex_unlock(&nfc_devlist_mutex);
320
321 return rc;
322}
323EXPORT_SYMBOL(nfc_register_device);
324
325/**
326 * nfc_unregister_device - unregister a nfc device in the nfc subsystem
327 *
328 * @dev: The nfc device to unregister
329 */
330void nfc_unregister_device(struct nfc_dev *dev)
331{
332 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
333
334 mutex_lock(&nfc_devlist_mutex);
335 nfc_devlist_generation++;
336
337 /* lock to avoid unregistering a device while an operation
338 is in progress */
339 device_lock(&dev->dev);
340 device_del(&dev->dev);
341 device_unlock(&dev->dev);
342
343 mutex_unlock(&nfc_devlist_mutex);
344}
345EXPORT_SYMBOL(nfc_unregister_device);
346
347static int __init nfc_init(void)
348{
349 nfc_info("NFC Core ver %s", VERSION);
350
351 return class_register(&nfc_class);
352}
353
354static void __exit nfc_exit(void)
355{
356 class_unregister(&nfc_class);
357}
358
359subsys_initcall(nfc_init);
360module_exit(nfc_exit);
361
362MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
363MODULE_DESCRIPTION("NFC Core ver " VERSION);
364MODULE_VERSION(VERSION);
365MODULE_LICENSE("GPL");
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
new file mode 100644
index 000000000000..55f83f86fe2c
--- /dev/null
+++ b/net/nfc/nfc.h
@@ -0,0 +1,78 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
6 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#ifndef __LOCAL_NFC_H
25#define __LOCAL_NFC_H
26
27#include <net/nfc.h>
28
29__attribute__((format (printf, 2, 3)))
30int nfc_printk(const char *level, const char *fmt, ...);
31
32#define nfc_info(fmt, arg...) nfc_printk(KERN_INFO, fmt, ##arg)
33#define nfc_err(fmt, arg...) nfc_printk(KERN_ERR, fmt, ##arg)
34#define nfc_dbg(fmt, arg...) pr_debug(fmt "\n", ##arg)
35
36extern int nfc_devlist_generation;
37extern struct mutex nfc_devlist_mutex;
38
39struct nfc_dev *nfc_get_device(unsigned idx);
40
41static inline void nfc_put_device(struct nfc_dev *dev)
42{
43 put_device(&dev->dev);
44}
45
46static inline void nfc_device_iter_init(struct class_dev_iter *iter)
47{
48 class_dev_iter_init(iter, &nfc_class, NULL, NULL);
49}
50
51static inline struct nfc_dev *nfc_device_iter_next(struct class_dev_iter *iter)
52{
53 struct device *d = class_dev_iter_next(iter);
54 if (!d)
55 return NULL;
56
57 return to_nfc_dev(d);
58}
59
60static inline void nfc_device_iter_exit(struct class_dev_iter *iter)
61{
62 class_dev_iter_exit(iter);
63}
64
65int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
66
67int nfc_stop_poll(struct nfc_dev *dev);
68
69int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
70
71int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
72
73int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
74 struct sk_buff *skb,
75 data_exchange_cb_t cb,
76 void *cb_context);
77
78#endif /* __LOCAL_NFC_H */