linux/net/nfc/core.c
<<
>>
Prefs
   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_dev_up - turn on the NFC device
  57 *
  58 * @dev: The nfc device to be turned on
  59 *
  60 * The device remains up until the nfc_dev_down function is called.
  61 */
  62int nfc_dev_up(struct nfc_dev *dev)
  63{
  64        int rc = 0;
  65
  66        nfc_dbg("dev_name=%s", dev_name(&dev->dev));
  67
  68        device_lock(&dev->dev);
  69
  70        if (!device_is_registered(&dev->dev)) {
  71                rc = -ENODEV;
  72                goto error;
  73        }
  74
  75        if (dev->dev_up) {
  76                rc = -EALREADY;
  77                goto error;
  78        }
  79
  80        if (dev->ops->dev_up)
  81                rc = dev->ops->dev_up(dev);
  82
  83        if (!rc)
  84                dev->dev_up = true;
  85
  86error:
  87        device_unlock(&dev->dev);
  88        return rc;
  89}
  90
  91/**
  92 * nfc_dev_down - turn off the NFC device
  93 *
  94 * @dev: The nfc device to be turned off
  95 */
  96int nfc_dev_down(struct nfc_dev *dev)
  97{
  98        int rc = 0;
  99
 100        nfc_dbg("dev_name=%s", dev_name(&dev->dev));
 101
 102        device_lock(&dev->dev);
 103
 104        if (!device_is_registered(&dev->dev)) {
 105                rc = -ENODEV;
 106                goto error;
 107        }
 108
 109        if (!dev->dev_up) {
 110                rc = -EALREADY;
 111                goto error;
 112        }
 113
 114        if (dev->polling || dev->remote_activated) {
 115                rc = -EBUSY;
 116                goto error;
 117        }
 118
 119        if (dev->ops->dev_down)
 120                dev->ops->dev_down(dev);
 121
 122        dev->dev_up = false;
 123
 124error:
 125        device_unlock(&dev->dev);
 126        return rc;
 127}
 128
 129/**
 130 * nfc_start_poll - start polling for nfc targets
 131 *
 132 * @dev: The nfc device that must start polling
 133 * @protocols: bitset of nfc protocols that must be used for polling
 134 *
 135 * The device remains polling for targets until a target is found or
 136 * the nfc_stop_poll function is called.
 137 */
 138int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
 139{
 140        int rc;
 141
 142        nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols);
 143
 144        if (!protocols)
 145                return -EINVAL;
 146
 147        device_lock(&dev->dev);
 148
 149        if (!device_is_registered(&dev->dev)) {
 150                rc = -ENODEV;
 151                goto error;
 152        }
 153
 154        if (dev->polling) {
 155                rc = -EBUSY;
 156                goto error;
 157        }
 158
 159        rc = dev->ops->start_poll(dev, protocols);
 160        if (!rc)
 161                dev->polling = true;
 162
 163error:
 164        device_unlock(&dev->dev);
 165        return rc;
 166}
 167
 168/**
 169 * nfc_stop_poll - stop polling for nfc targets
 170 *
 171 * @dev: The nfc device that must stop polling
 172 */
 173int nfc_stop_poll(struct nfc_dev *dev)
 174{
 175        int rc = 0;
 176
 177        nfc_dbg("dev_name=%s", dev_name(&dev->dev));
 178
 179        device_lock(&dev->dev);
 180
 181        if (!device_is_registered(&dev->dev)) {
 182                rc = -ENODEV;
 183                goto error;
 184        }
 185
 186        if (!dev->polling) {
 187                rc = -EINVAL;
 188                goto error;
 189        }
 190
 191        dev->ops->stop_poll(dev);
 192        dev->polling = false;
 193
 194error:
 195        device_unlock(&dev->dev);
 196        return rc;
 197}
 198
 199/**
 200 * nfc_activate_target - prepare the target for data exchange
 201 *
 202 * @dev: The nfc device that found the target
 203 * @target_idx: index of the target that must be activated
 204 * @protocol: nfc protocol that will be used for data exchange
 205 */
 206int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
 207{
 208        int rc;
 209
 210        nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev),
 211                                                        target_idx, protocol);
 212
 213        device_lock(&dev->dev);
 214
 215        if (!device_is_registered(&dev->dev)) {
 216                rc = -ENODEV;
 217                goto error;
 218        }
 219
 220        rc = dev->ops->activate_target(dev, target_idx, protocol);
 221        if (!rc)
 222                dev->remote_activated = true;
 223
 224error:
 225        device_unlock(&dev->dev);
 226        return rc;
 227}
 228
 229/**
 230 * nfc_deactivate_target - deactivate a nfc target
 231 *
 232 * @dev: The nfc device that found the target
 233 * @target_idx: index of the target that must be deactivated
 234 */
 235int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
 236{
 237        int rc = 0;
 238
 239        nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx);
 240
 241        device_lock(&dev->dev);
 242
 243        if (!device_is_registered(&dev->dev)) {
 244                rc = -ENODEV;
 245                goto error;
 246        }
 247
 248        dev->ops->deactivate_target(dev, target_idx);
 249        dev->remote_activated = false;
 250
 251error:
 252        device_unlock(&dev->dev);
 253        return rc;
 254}
 255
 256/**
 257 * nfc_data_exchange - transceive data
 258 *
 259 * @dev: The nfc device that found the target
 260 * @target_idx: index of the target
 261 * @skb: data to be sent
 262 * @cb: callback called when the response is received
 263 * @cb_context: parameter for the callback function
 264 *
 265 * The user must wait for the callback before calling this function again.
 266 */
 267int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
 268                                        struct sk_buff *skb,
 269                                        data_exchange_cb_t cb,
 270                                        void *cb_context)
 271{
 272        int rc;
 273
 274        nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev),
 275                                                        target_idx, skb->len);
 276
 277        device_lock(&dev->dev);
 278
 279        if (!device_is_registered(&dev->dev)) {
 280                rc = -ENODEV;
 281                kfree_skb(skb);
 282                goto error;
 283        }
 284
 285        rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context);
 286
 287error:
 288        device_unlock(&dev->dev);
 289        return rc;
 290}
 291
 292/**
 293 * nfc_alloc_skb - allocate a skb for data exchange responses
 294 *
 295 * @size: size to allocate
 296 * @gfp: gfp flags
 297 */
 298struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
 299{
 300        struct sk_buff *skb;
 301        unsigned int total_size;
 302
 303        total_size = size + 1;
 304        skb = alloc_skb(total_size, gfp);
 305
 306        if (skb)
 307                skb_reserve(skb, 1);
 308
 309        return skb;
 310}
 311EXPORT_SYMBOL(nfc_alloc_skb);
 312
 313/**
 314 * nfc_targets_found - inform that targets were found
 315 *
 316 * @dev: The nfc device that found the targets
 317 * @targets: array of nfc targets found
 318 * @ntargets: targets array size
 319 *
 320 * The device driver must call this function when one or many nfc targets
 321 * are found. After calling this function, the device driver must stop
 322 * polling for targets.
 323 */
 324int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
 325                                                        int n_targets)
 326{
 327        int i;
 328
 329        nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets);
 330
 331        dev->polling = false;
 332
 333        for (i = 0; i < n_targets; i++)
 334                targets[i].idx = dev->target_idx++;
 335
 336        spin_lock_bh(&dev->targets_lock);
 337
 338        dev->targets_generation++;
 339
 340        kfree(dev->targets);
 341        dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
 342                                                                GFP_ATOMIC);
 343
 344        if (!dev->targets) {
 345                dev->n_targets = 0;
 346                spin_unlock_bh(&dev->targets_lock);
 347                return -ENOMEM;
 348        }
 349
 350        dev->n_targets = n_targets;
 351        spin_unlock_bh(&dev->targets_lock);
 352
 353        nfc_genl_targets_found(dev);
 354
 355        return 0;
 356}
 357EXPORT_SYMBOL(nfc_targets_found);
 358
 359static void nfc_release(struct device *d)
 360{
 361        struct nfc_dev *dev = to_nfc_dev(d);
 362
 363        nfc_dbg("dev_name=%s", dev_name(&dev->dev));
 364
 365        nfc_genl_data_exit(&dev->genl_data);
 366        kfree(dev->targets);
 367        kfree(dev);
 368}
 369
 370struct class nfc_class = {
 371        .name = "nfc",
 372        .dev_release = nfc_release,
 373};
 374EXPORT_SYMBOL(nfc_class);
 375
 376static int match_idx(struct device *d, void *data)
 377{
 378        struct nfc_dev *dev = to_nfc_dev(d);
 379        unsigned *idx = data;
 380
 381        return dev->idx == *idx;
 382}
 383
 384struct nfc_dev *nfc_get_device(unsigned idx)
 385{
 386        struct device *d;
 387
 388        d = class_find_device(&nfc_class, NULL, &idx, match_idx);
 389        if (!d)
 390                return NULL;
 391
 392        return to_nfc_dev(d);
 393}
 394
 395/**
 396 * nfc_allocate_device - allocate a new nfc device
 397 *
 398 * @ops: device operations
 399 * @supported_protocols: NFC protocols supported by the device
 400 */
 401struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
 402                                        u32 supported_protocols,
 403                                        int tx_headroom,
 404                                        int tx_tailroom)
 405{
 406        static atomic_t dev_no = ATOMIC_INIT(0);
 407        struct nfc_dev *dev;
 408
 409        if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
 410                !ops->deactivate_target || !ops->data_exchange)
 411                return NULL;
 412
 413        if (!supported_protocols)
 414                return NULL;
 415
 416        dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);
 417        if (!dev)
 418                return NULL;
 419
 420        dev->dev.class = &nfc_class;
 421        dev->idx = atomic_inc_return(&dev_no) - 1;
 422        dev_set_name(&dev->dev, "nfc%d", dev->idx);
 423        device_initialize(&dev->dev);
 424
 425        dev->ops = ops;
 426        dev->supported_protocols = supported_protocols;
 427        dev->tx_headroom = tx_headroom;
 428        dev->tx_tailroom = tx_tailroom;
 429
 430        spin_lock_init(&dev->targets_lock);
 431        nfc_genl_data_init(&dev->genl_data);
 432
 433        /* first generation must not be 0 */
 434        dev->targets_generation = 1;
 435
 436        return dev;
 437}
 438EXPORT_SYMBOL(nfc_allocate_device);
 439
 440/**
 441 * nfc_register_device - register a nfc device in the nfc subsystem
 442 *
 443 * @dev: The nfc device to register
 444 */
 445int nfc_register_device(struct nfc_dev *dev)
 446{
 447        int rc;
 448
 449        nfc_dbg("dev_name=%s", dev_name(&dev->dev));
 450
 451        mutex_lock(&nfc_devlist_mutex);
 452        nfc_devlist_generation++;
 453        rc = device_add(&dev->dev);
 454        mutex_unlock(&nfc_devlist_mutex);
 455
 456        if (rc < 0)
 457                return rc;
 458
 459        rc = nfc_genl_device_added(dev);
 460        if (rc)
 461                nfc_dbg("The userspace won't be notified that the device %s was"
 462                                                " added", dev_name(&dev->dev));
 463
 464
 465        return 0;
 466}
 467EXPORT_SYMBOL(nfc_register_device);
 468
 469/**
 470 * nfc_unregister_device - unregister a nfc device in the nfc subsystem
 471 *
 472 * @dev: The nfc device to unregister
 473 */
 474void nfc_unregister_device(struct nfc_dev *dev)
 475{
 476        int rc;
 477
 478        nfc_dbg("dev_name=%s", dev_name(&dev->dev));
 479
 480        mutex_lock(&nfc_devlist_mutex);
 481        nfc_devlist_generation++;
 482
 483        /* lock to avoid unregistering a device while an operation
 484           is in progress */
 485        device_lock(&dev->dev);
 486        device_del(&dev->dev);
 487        device_unlock(&dev->dev);
 488
 489        mutex_unlock(&nfc_devlist_mutex);
 490
 491        rc = nfc_genl_device_removed(dev);
 492        if (rc)
 493                nfc_dbg("The userspace won't be notified that the device %s"
 494                                        " was removed", dev_name(&dev->dev));
 495
 496}
 497EXPORT_SYMBOL(nfc_unregister_device);
 498
 499static int __init nfc_init(void)
 500{
 501        int rc;
 502
 503        nfc_info("NFC Core ver %s", VERSION);
 504
 505        rc = class_register(&nfc_class);
 506        if (rc)
 507                return rc;
 508
 509        rc = nfc_genl_init();
 510        if (rc)
 511                goto err_genl;
 512
 513        /* the first generation must not be 0 */
 514        nfc_devlist_generation = 1;
 515
 516        rc = rawsock_init();
 517        if (rc)
 518                goto err_rawsock;
 519
 520        rc = af_nfc_init();
 521        if (rc)
 522                goto err_af_nfc;
 523
 524        return 0;
 525
 526err_af_nfc:
 527        rawsock_exit();
 528err_rawsock:
 529        nfc_genl_exit();
 530err_genl:
 531        class_unregister(&nfc_class);
 532        return rc;
 533}
 534
 535static void __exit nfc_exit(void)
 536{
 537        af_nfc_exit();
 538        rawsock_exit();
 539        nfc_genl_exit();
 540        class_unregister(&nfc_class);
 541}
 542
 543subsys_initcall(nfc_init);
 544module_exit(nfc_exit);
 545
 546MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
 547MODULE_DESCRIPTION("NFC Core ver " VERSION);
 548MODULE_VERSION(VERSION);
 549MODULE_LICENSE("GPL");
 550
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.