aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/core.c')
-rw-r--r--net/nfc/core.c157
1 files changed, 119 insertions, 38 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 9f6ce011d35d..ff749794bc5b 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -29,6 +29,8 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/nfc.h> 30#include <linux/nfc.h>
31 31
32#include <net/genetlink.h>
33
32#include "nfc.h" 34#include "nfc.h"
33 35
34#define VERSION "0.1" 36#define VERSION "0.1"
@@ -121,14 +123,14 @@ error:
121 * The device remains polling for targets until a target is found or 123 * The device remains polling for targets until a target is found or
122 * the nfc_stop_poll function is called. 124 * the nfc_stop_poll function is called.
123 */ 125 */
124int nfc_start_poll(struct nfc_dev *dev, u32 protocols) 126int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
125{ 127{
126 int rc; 128 int rc;
127 129
128 pr_debug("dev_name=%s protocols=0x%x\n", 130 pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n",
129 dev_name(&dev->dev), protocols); 131 dev_name(&dev->dev), im_protocols, tm_protocols);
130 132
131 if (!protocols) 133 if (!im_protocols && !tm_protocols)
132 return -EINVAL; 134 return -EINVAL;
133 135
134 device_lock(&dev->dev); 136 device_lock(&dev->dev);
@@ -143,9 +145,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
143 goto error; 145 goto error;
144 } 146 }
145 147
146 rc = dev->ops->start_poll(dev, protocols); 148 rc = dev->ops->start_poll(dev, im_protocols, tm_protocols);
147 if (!rc) 149 if (!rc) {
148 dev->polling = true; 150 dev->polling = true;
151 dev->rf_mode = NFC_RF_NONE;
152 }
149 153
150error: 154error:
151 device_unlock(&dev->dev); 155 device_unlock(&dev->dev);
@@ -235,8 +239,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
235 } 239 }
236 240
237 rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); 241 rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len);
238 if (!rc) 242 if (!rc) {
239 dev->active_target = target; 243 dev->active_target = target;
244 dev->rf_mode = NFC_RF_INITIATOR;
245 }
240 246
241error: 247error:
242 device_unlock(&dev->dev); 248 device_unlock(&dev->dev);
@@ -264,11 +270,6 @@ int nfc_dep_link_down(struct nfc_dev *dev)
264 goto error; 270 goto error;
265 } 271 }
266 272
267 if (dev->dep_rf_mode == NFC_RF_TARGET) {
268 rc = -EOPNOTSUPP;
269 goto error;
270 }
271
272 rc = dev->ops->dep_link_down(dev); 273 rc = dev->ops->dep_link_down(dev);
273 if (!rc) { 274 if (!rc) {
274 dev->dep_link_up = false; 275 dev->dep_link_up = false;
@@ -286,7 +287,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
286 u8 comm_mode, u8 rf_mode) 287 u8 comm_mode, u8 rf_mode)
287{ 288{
288 dev->dep_link_up = true; 289 dev->dep_link_up = true;
289 dev->dep_rf_mode = rf_mode;
290 290
291 nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); 291 nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode);
292 292
@@ -330,6 +330,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
330 rc = dev->ops->activate_target(dev, target, protocol); 330 rc = dev->ops->activate_target(dev, target, protocol);
331 if (!rc) { 331 if (!rc) {
332 dev->active_target = target; 332 dev->active_target = target;
333 dev->rf_mode = NFC_RF_INITIATOR;
333 334
334 if (dev->ops->check_presence) 335 if (dev->ops->check_presence)
335 mod_timer(&dev->check_pres_timer, jiffies + 336 mod_timer(&dev->check_pres_timer, jiffies +
@@ -409,27 +410,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
409 goto error; 410 goto error;
410 } 411 }
411 412
412 if (dev->active_target == NULL) { 413 if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) {
413 rc = -ENOTCONN; 414 if (dev->active_target->idx != target_idx) {
414 kfree_skb(skb); 415 rc = -EADDRNOTAVAIL;
415 goto error; 416 kfree_skb(skb);
416 } 417 goto error;
418 }
417 419
418 if (dev->active_target->idx != target_idx) { 420 if (dev->ops->check_presence)
419 rc = -EADDRNOTAVAIL; 421 del_timer_sync(&dev->check_pres_timer);
422
423 rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb,
424 cb_context);
425
426 if (!rc && dev->ops->check_presence)
427 mod_timer(&dev->check_pres_timer, jiffies +
428 msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
429 } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) {
430 rc = dev->ops->tm_send(dev, skb);
431 } else {
432 rc = -ENOTCONN;
420 kfree_skb(skb); 433 kfree_skb(skb);
421 goto error; 434 goto error;
422 } 435 }
423 436
424 if (dev->ops->check_presence)
425 del_timer_sync(&dev->check_pres_timer);
426
427 rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb,
428 cb_context);
429
430 if (!rc && dev->ops->check_presence)
431 mod_timer(&dev->check_pres_timer, jiffies +
432 msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
433 437
434error: 438error:
435 device_unlock(&dev->dev); 439 device_unlock(&dev->dev);
@@ -447,6 +451,63 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
447} 451}
448EXPORT_SYMBOL(nfc_set_remote_general_bytes); 452EXPORT_SYMBOL(nfc_set_remote_general_bytes);
449 453
454u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len)
455{
456 pr_debug("dev_name=%s\n", dev_name(&dev->dev));
457
458 return nfc_llcp_general_bytes(dev, gb_len);
459}
460EXPORT_SYMBOL(nfc_get_local_general_bytes);
461
462int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb)
463{
464 /* Only LLCP target mode for now */
465 if (dev->dep_link_up == false) {
466 kfree_skb(skb);
467 return -ENOLINK;
468 }
469
470 return nfc_llcp_data_received(dev, skb);
471}
472EXPORT_SYMBOL(nfc_tm_data_received);
473
474int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
475 u8 *gb, size_t gb_len)
476{
477 int rc;
478
479 device_lock(&dev->dev);
480
481 dev->polling = false;
482
483 if (gb != NULL) {
484 rc = nfc_set_remote_general_bytes(dev, gb, gb_len);
485 if (rc < 0)
486 goto out;
487 }
488
489 dev->rf_mode = NFC_RF_TARGET;
490
491 if (protocol == NFC_PROTO_NFC_DEP_MASK)
492 nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET);
493
494 rc = nfc_genl_tm_activated(dev, protocol);
495
496out:
497 device_unlock(&dev->dev);
498
499 return rc;
500}
501EXPORT_SYMBOL(nfc_tm_activated);
502
503int nfc_tm_deactivated(struct nfc_dev *dev)
504{
505 dev->dep_link_up = false;
506
507 return nfc_genl_tm_deactivated(dev);
508}
509EXPORT_SYMBOL(nfc_tm_deactivated);
510
450/** 511/**
451 * nfc_alloc_send_skb - allocate a skb for data exchange responses 512 * nfc_alloc_send_skb - allocate a skb for data exchange responses
452 * 513 *
@@ -501,6 +562,8 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
501 * The device driver must call this function when one or many nfc targets 562 * The device driver must call this function when one or many nfc targets
502 * are found. After calling this function, the device driver must stop 563 * are found. After calling this function, the device driver must stop
503 * polling for targets. 564 * polling for targets.
565 * NOTE: This function can be called with targets=NULL and n_targets=0 to
566 * notify a driver error, meaning that the polling operation cannot complete.
504 * IMPORTANT: this function must not be called from an atomic context. 567 * IMPORTANT: this function must not be called from an atomic context.
505 * In addition, it must also not be called from a context that would prevent 568 * In addition, it must also not be called from a context that would prevent
506 * the NFC Core to call other nfc ops entry point concurrently. 569 * the NFC Core to call other nfc ops entry point concurrently.
@@ -512,23 +575,33 @@ int nfc_targets_found(struct nfc_dev *dev,
512 575
513 pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); 576 pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
514 577
515 dev->polling = false;
516
517 for (i = 0; i < n_targets; i++) 578 for (i = 0; i < n_targets; i++)
518 targets[i].idx = dev->target_next_idx++; 579 targets[i].idx = dev->target_next_idx++;
519 580
520 device_lock(&dev->dev); 581 device_lock(&dev->dev);
521 582
583 if (dev->polling == false) {
584 device_unlock(&dev->dev);
585 return 0;
586 }
587
588 dev->polling = false;
589
522 dev->targets_generation++; 590 dev->targets_generation++;
523 591
524 kfree(dev->targets); 592 kfree(dev->targets);
525 dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target), 593 dev->targets = NULL;
526 GFP_ATOMIC);
527 594
528 if (!dev->targets) { 595 if (targets) {
529 dev->n_targets = 0; 596 dev->targets = kmemdup(targets,
530 device_unlock(&dev->dev); 597 n_targets * sizeof(struct nfc_target),
531 return -ENOMEM; 598 GFP_ATOMIC);
599
600 if (!dev->targets) {
601 dev->n_targets = 0;
602 device_unlock(&dev->dev);
603 return -ENOMEM;
604 }
532 } 605 }
533 606
534 dev->n_targets = n_targets; 607 dev->n_targets = n_targets;
@@ -592,6 +665,12 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
592} 665}
593EXPORT_SYMBOL(nfc_target_lost); 666EXPORT_SYMBOL(nfc_target_lost);
594 667
668inline void nfc_driver_failure(struct nfc_dev *dev, int err)
669{
670 nfc_targets_found(dev, NULL, 0);
671}
672EXPORT_SYMBOL(nfc_driver_failure);
673
595static void nfc_release(struct device *d) 674static void nfc_release(struct device *d)
596{ 675{
597 struct nfc_dev *dev = to_nfc_dev(d); 676 struct nfc_dev *dev = to_nfc_dev(d);
@@ -678,7 +757,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
678 struct nfc_dev *dev; 757 struct nfc_dev *dev;
679 758
680 if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || 759 if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
681 !ops->deactivate_target || !ops->data_exchange) 760 !ops->deactivate_target || !ops->im_transceive)
682 return NULL; 761 return NULL;
683 762
684 if (!supported_protocols) 763 if (!supported_protocols)
@@ -847,3 +926,5 @@ MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
847MODULE_DESCRIPTION("NFC Core ver " VERSION); 926MODULE_DESCRIPTION("NFC Core ver " VERSION);
848MODULE_VERSION(VERSION); 927MODULE_VERSION(VERSION);
849MODULE_LICENSE("GPL"); 928MODULE_LICENSE("GPL");
929MODULE_ALIAS_NETPROTO(PF_NFC);
930MODULE_ALIAS_GENL_FAMILY(NFC_GENL_NAME);