Commit | Line | Data |
---|---|---|
7cbe0ff3 TE |
1 | /* |
2 | * NFC hardware simulation driver | |
3 | * Copyright (c) 2013, Intel Corporation. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms and conditions of the GNU General Public License, | |
7 | * version 2, as published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | */ | |
15 | ||
16 | #include <linux/device.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/module.h> | |
19 | #include <linux/nfc.h> | |
20 | #include <net/nfc/nfc.h> | |
21 | ||
073a625f | 22 | #define DEV_ERR(_dev, fmt, args...) nfc_err(&_dev->nfc_dev->dev, \ |
7cbe0ff3 TE |
23 | "%s: " fmt, __func__, ## args) |
24 | ||
b4834839 | 25 | #define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \ |
7cbe0ff3 TE |
26 | "%s: " fmt, __func__, ## args) |
27 | ||
28 | #define NFCSIM_VERSION "0.1" | |
29 | ||
30 | #define NFCSIM_POLL_NONE 0 | |
31 | #define NFCSIM_POLL_INITIATOR 1 | |
32 | #define NFCSIM_POLL_TARGET 2 | |
33 | #define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET) | |
34 | ||
a440f1aa SS |
35 | #define RX_DEFAULT_DELAY 5 |
36 | ||
7cbe0ff3 TE |
37 | struct nfcsim { |
38 | struct nfc_dev *nfc_dev; | |
39 | ||
40 | struct mutex lock; | |
41 | ||
42 | struct delayed_work recv_work; | |
43 | ||
44 | struct sk_buff *clone_skb; | |
45 | ||
46 | struct delayed_work poll_work; | |
47 | u8 polling_mode; | |
48 | u8 curr_polling_mode; | |
49 | ||
50 | u8 shutting_down; | |
51 | ||
52 | u8 up; | |
53 | ||
54 | u8 initiator; | |
55 | ||
a440f1aa SS |
56 | u32 rx_delay; |
57 | ||
7cbe0ff3 TE |
58 | data_exchange_cb_t cb; |
59 | void *cb_context; | |
60 | ||
61 | struct nfcsim *peer_dev; | |
62 | }; | |
63 | ||
64 | static struct nfcsim *dev0; | |
65 | static struct nfcsim *dev1; | |
66 | ||
40dac370 | 67 | static struct workqueue_struct *wq; |
7cbe0ff3 TE |
68 | |
69 | static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) | |
70 | { | |
b4834839 | 71 | DEV_DBG(dev, "shutdown=%d\n", shutdown); |
7cbe0ff3 TE |
72 | |
73 | mutex_lock(&dev->lock); | |
74 | ||
75 | dev->polling_mode = NFCSIM_POLL_NONE; | |
76 | dev->shutting_down = shutdown; | |
77 | dev->cb = NULL; | |
78 | dev_kfree_skb(dev->clone_skb); | |
79 | dev->clone_skb = NULL; | |
80 | ||
81 | mutex_unlock(&dev->lock); | |
82 | ||
83 | cancel_delayed_work_sync(&dev->poll_work); | |
84 | cancel_delayed_work_sync(&dev->recv_work); | |
85 | } | |
86 | ||
87 | static int nfcsim_target_found(struct nfcsim *dev) | |
88 | { | |
89 | struct nfc_target nfc_tgt; | |
90 | ||
b4834839 | 91 | DEV_DBG(dev, "\n"); |
7cbe0ff3 TE |
92 | |
93 | memset(&nfc_tgt, 0, sizeof(struct nfc_target)); | |
94 | ||
95 | nfc_tgt.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | |
96 | nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); | |
97 | ||
98 | return 0; | |
99 | } | |
100 | ||
101 | static int nfcsim_dev_up(struct nfc_dev *nfc_dev) | |
102 | { | |
103 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
104 | ||
b4834839 | 105 | DEV_DBG(dev, "\n"); |
7cbe0ff3 TE |
106 | |
107 | mutex_lock(&dev->lock); | |
108 | ||
109 | dev->up = 1; | |
110 | ||
111 | mutex_unlock(&dev->lock); | |
112 | ||
113 | return 0; | |
114 | } | |
115 | ||
116 | static int nfcsim_dev_down(struct nfc_dev *nfc_dev) | |
117 | { | |
118 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
119 | ||
b4834839 | 120 | DEV_DBG(dev, "\n"); |
7cbe0ff3 TE |
121 | |
122 | mutex_lock(&dev->lock); | |
123 | ||
124 | dev->up = 0; | |
125 | ||
126 | mutex_unlock(&dev->lock); | |
127 | ||
128 | return 0; | |
129 | } | |
130 | ||
131 | static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, | |
132 | struct nfc_target *target, | |
133 | u8 comm_mode, u8 *gb, size_t gb_len) | |
134 | { | |
135 | int rc; | |
136 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
137 | struct nfcsim *peer = dev->peer_dev; | |
138 | u8 *remote_gb; | |
139 | size_t remote_gb_len; | |
140 | ||
141 | DEV_DBG(dev, "target_idx: %d, comm_mode: %d\n", target->idx, comm_mode); | |
142 | ||
143 | mutex_lock(&peer->lock); | |
144 | ||
145 | nfc_tm_activated(peer->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | |
146 | NFC_COMM_ACTIVE, gb, gb_len); | |
147 | ||
148 | remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); | |
149 | if (!remote_gb) { | |
073a625f | 150 | DEV_ERR(peer, "Can't get remote general bytes\n"); |
7cbe0ff3 TE |
151 | |
152 | mutex_unlock(&peer->lock); | |
153 | return -EINVAL; | |
154 | } | |
155 | ||
156 | mutex_unlock(&peer->lock); | |
157 | ||
158 | mutex_lock(&dev->lock); | |
159 | ||
160 | rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); | |
161 | if (rc) { | |
073a625f | 162 | DEV_ERR(dev, "Can't set remote general bytes\n"); |
7cbe0ff3 TE |
163 | mutex_unlock(&dev->lock); |
164 | return rc; | |
165 | } | |
166 | ||
167 | rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_ACTIVE, | |
168 | NFC_RF_INITIATOR); | |
169 | ||
170 | mutex_unlock(&dev->lock); | |
171 | ||
172 | return rc; | |
173 | } | |
174 | ||
175 | static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) | |
176 | { | |
177 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
178 | ||
b4834839 | 179 | DEV_DBG(dev, "\n"); |
7cbe0ff3 TE |
180 | |
181 | nfcsim_cleanup_dev(dev, 0); | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | static int nfcsim_start_poll(struct nfc_dev *nfc_dev, | |
187 | u32 im_protocols, u32 tm_protocols) | |
188 | { | |
189 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
190 | int rc; | |
191 | ||
192 | mutex_lock(&dev->lock); | |
193 | ||
194 | if (dev->polling_mode != NFCSIM_POLL_NONE) { | |
073a625f | 195 | DEV_ERR(dev, "Already in polling mode\n"); |
7cbe0ff3 TE |
196 | rc = -EBUSY; |
197 | goto exit; | |
198 | } | |
199 | ||
200 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) | |
201 | dev->polling_mode |= NFCSIM_POLL_INITIATOR; | |
202 | ||
203 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) | |
204 | dev->polling_mode |= NFCSIM_POLL_TARGET; | |
205 | ||
206 | if (dev->polling_mode == NFCSIM_POLL_NONE) { | |
073a625f | 207 | DEV_ERR(dev, "Unsupported polling mode\n"); |
7cbe0ff3 TE |
208 | rc = -EINVAL; |
209 | goto exit; | |
210 | } | |
211 | ||
212 | dev->initiator = 0; | |
213 | dev->curr_polling_mode = NFCSIM_POLL_NONE; | |
214 | ||
215 | queue_delayed_work(wq, &dev->poll_work, 0); | |
216 | ||
b4834839 | 217 | DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X\n", im_protocols, |
7cbe0ff3 TE |
218 | tm_protocols); |
219 | ||
220 | rc = 0; | |
221 | exit: | |
222 | mutex_unlock(&dev->lock); | |
223 | ||
224 | return rc; | |
225 | } | |
226 | ||
227 | static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) | |
228 | { | |
229 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
230 | ||
b4834839 | 231 | DEV_DBG(dev, "Stop poll\n"); |
7cbe0ff3 TE |
232 | |
233 | mutex_lock(&dev->lock); | |
234 | ||
235 | dev->polling_mode = NFCSIM_POLL_NONE; | |
236 | ||
237 | mutex_unlock(&dev->lock); | |
238 | ||
239 | cancel_delayed_work_sync(&dev->poll_work); | |
240 | } | |
241 | ||
242 | static int nfcsim_activate_target(struct nfc_dev *nfc_dev, | |
243 | struct nfc_target *target, u32 protocol) | |
244 | { | |
245 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
246 | ||
b4834839 | 247 | DEV_DBG(dev, "\n"); |
7cbe0ff3 TE |
248 | |
249 | return -ENOTSUPP; | |
250 | } | |
251 | ||
252 | static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, | |
96d4581f | 253 | struct nfc_target *target, u8 mode) |
7cbe0ff3 TE |
254 | { |
255 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
256 | ||
b4834839 | 257 | DEV_DBG(dev, "\n"); |
7cbe0ff3 TE |
258 | } |
259 | ||
260 | static void nfcsim_wq_recv(struct work_struct *work) | |
261 | { | |
262 | struct nfcsim *dev = container_of(work, struct nfcsim, | |
263 | recv_work.work); | |
264 | ||
265 | mutex_lock(&dev->lock); | |
266 | ||
267 | if (dev->shutting_down || !dev->up || !dev->clone_skb) { | |
268 | dev_kfree_skb(dev->clone_skb); | |
269 | goto exit; | |
270 | } | |
271 | ||
272 | if (dev->initiator) { | |
273 | if (!dev->cb) { | |
073a625f | 274 | DEV_ERR(dev, "Null recv callback\n"); |
7cbe0ff3 TE |
275 | dev_kfree_skb(dev->clone_skb); |
276 | goto exit; | |
277 | } | |
278 | ||
279 | dev->cb(dev->cb_context, dev->clone_skb, 0); | |
280 | dev->cb = NULL; | |
281 | } else { | |
282 | nfc_tm_data_received(dev->nfc_dev, dev->clone_skb); | |
283 | } | |
284 | ||
285 | exit: | |
286 | dev->clone_skb = NULL; | |
287 | ||
288 | mutex_unlock(&dev->lock); | |
289 | } | |
290 | ||
291 | static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, | |
292 | struct sk_buff *skb, data_exchange_cb_t cb, | |
293 | void *cb_context) | |
294 | { | |
295 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | |
296 | struct nfcsim *peer = dev->peer_dev; | |
297 | int err; | |
298 | ||
299 | mutex_lock(&dev->lock); | |
300 | ||
301 | if (dev->shutting_down || !dev->up) { | |
302 | mutex_unlock(&dev->lock); | |
303 | err = -ENODEV; | |
304 | goto exit; | |
305 | } | |
306 | ||
307 | dev->cb = cb; | |
308 | dev->cb_context = cb_context; | |
309 | ||
310 | mutex_unlock(&dev->lock); | |
311 | ||
312 | mutex_lock(&peer->lock); | |
313 | ||
314 | peer->clone_skb = skb_clone(skb, GFP_KERNEL); | |
315 | ||
316 | if (!peer->clone_skb) { | |
073a625f | 317 | DEV_ERR(dev, "skb_clone failed\n"); |
7cbe0ff3 TE |
318 | mutex_unlock(&peer->lock); |
319 | err = -ENOMEM; | |
320 | goto exit; | |
321 | } | |
322 | ||
323 | /* This simulates an arbitrary transmission delay between the 2 devices. | |
324 | * If packet transmission occurs immediately between them, we have a | |
325 | * non-stop flow of several tens of thousands SYMM packets per second | |
326 | * and a burning cpu. | |
7cbe0ff3 | 327 | */ |
a440f1aa SS |
328 | queue_delayed_work(wq, &peer->recv_work, |
329 | msecs_to_jiffies(dev->rx_delay)); | |
7cbe0ff3 TE |
330 | |
331 | mutex_unlock(&peer->lock); | |
332 | ||
333 | err = 0; | |
334 | exit: | |
335 | dev_kfree_skb(skb); | |
336 | ||
337 | return err; | |
338 | } | |
339 | ||
340 | static int nfcsim_im_transceive(struct nfc_dev *nfc_dev, | |
341 | struct nfc_target *target, struct sk_buff *skb, | |
342 | data_exchange_cb_t cb, void *cb_context) | |
343 | { | |
344 | return nfcsim_tx(nfc_dev, target, skb, cb, cb_context); | |
345 | } | |
346 | ||
347 | static int nfcsim_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | |
348 | { | |
349 | return nfcsim_tx(nfc_dev, NULL, skb, NULL, NULL); | |
350 | } | |
351 | ||
352 | static struct nfc_ops nfcsim_nfc_ops = { | |
353 | .dev_up = nfcsim_dev_up, | |
354 | .dev_down = nfcsim_dev_down, | |
355 | .dep_link_up = nfcsim_dep_link_up, | |
356 | .dep_link_down = nfcsim_dep_link_down, | |
357 | .start_poll = nfcsim_start_poll, | |
358 | .stop_poll = nfcsim_stop_poll, | |
359 | .activate_target = nfcsim_activate_target, | |
360 | .deactivate_target = nfcsim_deactivate_target, | |
361 | .im_transceive = nfcsim_im_transceive, | |
362 | .tm_send = nfcsim_tm_send, | |
363 | }; | |
364 | ||
365 | static void nfcsim_set_polling_mode(struct nfcsim *dev) | |
366 | { | |
367 | if (dev->polling_mode == NFCSIM_POLL_NONE) { | |
368 | dev->curr_polling_mode = NFCSIM_POLL_NONE; | |
369 | return; | |
370 | } | |
371 | ||
372 | if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { | |
373 | if (dev->polling_mode & NFCSIM_POLL_INITIATOR) | |
374 | dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; | |
375 | else | |
376 | dev->curr_polling_mode = NFCSIM_POLL_TARGET; | |
377 | ||
378 | return; | |
379 | } | |
380 | ||
381 | if (dev->polling_mode == NFCSIM_POLL_DUAL) { | |
382 | if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) | |
383 | dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; | |
384 | else | |
385 | dev->curr_polling_mode = NFCSIM_POLL_TARGET; | |
386 | } | |
387 | } | |
388 | ||
389 | static void nfcsim_wq_poll(struct work_struct *work) | |
390 | { | |
391 | struct nfcsim *dev = container_of(work, struct nfcsim, poll_work.work); | |
392 | struct nfcsim *peer = dev->peer_dev; | |
393 | ||
394 | /* These work items run on an ordered workqueue and are therefore | |
395 | * serialized. So we can take both mutexes without being dead locked. | |
396 | */ | |
397 | mutex_lock(&dev->lock); | |
398 | mutex_lock(&peer->lock); | |
399 | ||
400 | nfcsim_set_polling_mode(dev); | |
401 | ||
402 | if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { | |
b4834839 | 403 | DEV_DBG(dev, "Not polling\n"); |
7cbe0ff3 TE |
404 | goto unlock; |
405 | } | |
406 | ||
407 | DEV_DBG(dev, "Polling as %s", | |
408 | dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? | |
b4834839 | 409 | "initiator\n" : "target\n"); |
7cbe0ff3 TE |
410 | |
411 | if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) | |
412 | goto sched_work; | |
413 | ||
414 | if (peer->curr_polling_mode == NFCSIM_POLL_TARGET) { | |
415 | peer->polling_mode = NFCSIM_POLL_NONE; | |
416 | dev->polling_mode = NFCSIM_POLL_NONE; | |
417 | ||
418 | dev->initiator = 1; | |
419 | ||
420 | nfcsim_target_found(dev); | |
421 | ||
422 | goto unlock; | |
423 | } | |
424 | ||
425 | sched_work: | |
426 | /* This defines the delay for an initiator to check if the other device | |
427 | * is polling in target mode. | |
428 | * If the device starts in dual mode polling, it switches between | |
429 | * initiator and target at every round. | |
430 | * Because the wq is ordered and only 1 work item is executed at a time, | |
431 | * we'll always have one device polling as initiator and the other as | |
432 | * target at some point, even if both are started in dual mode. | |
433 | */ | |
434 | queue_delayed_work(wq, &dev->poll_work, msecs_to_jiffies(200)); | |
435 | ||
436 | unlock: | |
437 | mutex_unlock(&peer->lock); | |
438 | mutex_unlock(&dev->lock); | |
439 | } | |
440 | ||
441 | static struct nfcsim *nfcsim_init_dev(void) | |
442 | { | |
443 | struct nfcsim *dev; | |
444 | int rc = -ENOMEM; | |
445 | ||
446 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | |
447 | if (dev == NULL) | |
448 | return ERR_PTR(-ENOMEM); | |
449 | ||
450 | mutex_init(&dev->lock); | |
451 | ||
452 | INIT_DELAYED_WORK(&dev->recv_work, nfcsim_wq_recv); | |
453 | INIT_DELAYED_WORK(&dev->poll_work, nfcsim_wq_poll); | |
454 | ||
455 | dev->nfc_dev = nfc_allocate_device(&nfcsim_nfc_ops, | |
456 | NFC_PROTO_NFC_DEP_MASK, | |
457 | 0, 0); | |
458 | if (!dev->nfc_dev) | |
459 | goto error; | |
460 | ||
461 | nfc_set_drvdata(dev->nfc_dev, dev); | |
462 | ||
463 | rc = nfc_register_device(dev->nfc_dev); | |
464 | if (rc) | |
465 | goto free_nfc_dev; | |
466 | ||
a440f1aa | 467 | dev->rx_delay = RX_DEFAULT_DELAY; |
7cbe0ff3 TE |
468 | return dev; |
469 | ||
470 | free_nfc_dev: | |
471 | nfc_free_device(dev->nfc_dev); | |
472 | ||
473 | error: | |
474 | kfree(dev); | |
475 | ||
476 | return ERR_PTR(rc); | |
477 | } | |
478 | ||
479 | static void nfcsim_free_device(struct nfcsim *dev) | |
480 | { | |
481 | nfc_unregister_device(dev->nfc_dev); | |
482 | ||
483 | nfc_free_device(dev->nfc_dev); | |
484 | ||
485 | kfree(dev); | |
486 | } | |
487 | ||
40dac370 | 488 | static int __init nfcsim_init(void) |
7cbe0ff3 TE |
489 | { |
490 | int rc; | |
491 | ||
492 | /* We need an ordered wq to ensure that poll_work items are executed | |
493 | * one at a time. | |
494 | */ | |
495 | wq = alloc_ordered_workqueue("nfcsim", 0); | |
496 | if (!wq) { | |
497 | rc = -ENOMEM; | |
498 | goto exit; | |
499 | } | |
500 | ||
501 | dev0 = nfcsim_init_dev(); | |
502 | if (IS_ERR(dev0)) { | |
503 | rc = PTR_ERR(dev0); | |
504 | goto exit; | |
505 | } | |
506 | ||
507 | dev1 = nfcsim_init_dev(); | |
508 | if (IS_ERR(dev1)) { | |
509 | kfree(dev0); | |
510 | ||
511 | rc = PTR_ERR(dev1); | |
512 | goto exit; | |
513 | } | |
514 | ||
515 | dev0->peer_dev = dev1; | |
516 | dev1->peer_dev = dev0; | |
517 | ||
518 | pr_debug("NFCsim " NFCSIM_VERSION " initialized\n"); | |
519 | ||
520 | rc = 0; | |
521 | exit: | |
522 | if (rc) | |
523 | pr_err("Failed to initialize nfcsim driver (%d)\n", | |
524 | rc); | |
525 | ||
526 | return rc; | |
527 | } | |
528 | ||
40dac370 | 529 | static void __exit nfcsim_exit(void) |
7cbe0ff3 TE |
530 | { |
531 | nfcsim_cleanup_dev(dev0, 1); | |
532 | nfcsim_cleanup_dev(dev1, 1); | |
533 | ||
534 | nfcsim_free_device(dev0); | |
535 | nfcsim_free_device(dev1); | |
536 | ||
537 | destroy_workqueue(wq); | |
538 | } | |
539 | ||
540 | module_init(nfcsim_init); | |
541 | module_exit(nfcsim_exit); | |
542 | ||
543 | MODULE_DESCRIPTION("NFCSim driver ver " NFCSIM_VERSION); | |
544 | MODULE_VERSION(NFCSIM_VERSION); | |
545 | MODULE_LICENSE("GPL"); |