root/drivers/nfc/nfcsim.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfcsim_link_new
  2. nfcsim_link_free
  3. nfcsim_link_recv_wake
  4. nfcsim_link_set_skb
  5. nfcsim_link_recv_cancel
  6. nfcsim_link_shutdown
  7. nfcsim_link_recv_skb
  8. nfcsim_send_wq
  9. nfcsim_recv_wq
  10. nfcsim_send
  11. nfcsim_abort_cmd
  12. nfcsim_switch_rf
  13. nfcsim_in_configure_hw
  14. nfcsim_in_send_cmd
  15. nfcsim_tg_configure_hw
  16. nfcsim_tg_send_cmd
  17. nfcsim_tg_listen
  18. nfcsim_debugfs_init
  19. nfcsim_debugfs_remove
  20. nfcsim_debugfs_init_dev
  21. nfcsim_device_new
  22. nfcsim_device_free
  23. nfcsim_init
  24. nfcsim_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * NFC hardware simulation driver
   4  * Copyright (c) 2013, Intel Corporation.
   5  */
   6 
   7 #include <linux/device.h>
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/ctype.h>
  11 #include <linux/debugfs.h>
  12 #include <linux/nfc.h>
  13 #include <net/nfc/nfc.h>
  14 #include <net/nfc/digital.h>
  15 
  16 #define NFCSIM_ERR(d, fmt, args...) nfc_err(&d->nfc_digital_dev->nfc_dev->dev, \
  17                                             "%s: " fmt, __func__, ## args)
  18 
  19 #define NFCSIM_DBG(d, fmt, args...) dev_dbg(&d->nfc_digital_dev->nfc_dev->dev, \
  20                                             "%s: " fmt, __func__, ## args)
  21 
  22 #define NFCSIM_VERSION "0.2"
  23 
  24 #define NFCSIM_MODE_NONE        0
  25 #define NFCSIM_MODE_INITIATOR   1
  26 #define NFCSIM_MODE_TARGET      2
  27 
  28 #define NFCSIM_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC   | \
  29                              NFC_DIGITAL_DRV_CAPS_TG_CRC)
  30 
  31 struct nfcsim {
  32         struct nfc_digital_dev *nfc_digital_dev;
  33 
  34         struct work_struct recv_work;
  35         struct delayed_work send_work;
  36 
  37         struct nfcsim_link *link_in;
  38         struct nfcsim_link *link_out;
  39 
  40         bool up;
  41         u8 mode;
  42         u8 rf_tech;
  43 
  44         u16 recv_timeout;
  45 
  46         nfc_digital_cmd_complete_t cb;
  47         void *arg;
  48 
  49         u8 dropframe;
  50 };
  51 
  52 struct nfcsim_link {
  53         struct mutex lock;
  54 
  55         u8 rf_tech;
  56         u8 mode;
  57 
  58         u8 shutdown;
  59 
  60         struct sk_buff *skb;
  61         wait_queue_head_t recv_wait;
  62         u8 cond;
  63 };
  64 
  65 static struct nfcsim_link *nfcsim_link_new(void)
  66 {
  67         struct nfcsim_link *link;
  68 
  69         link = kzalloc(sizeof(struct nfcsim_link), GFP_KERNEL);
  70         if (!link)
  71                 return NULL;
  72 
  73         mutex_init(&link->lock);
  74         init_waitqueue_head(&link->recv_wait);
  75 
  76         return link;
  77 }
  78 
  79 static void nfcsim_link_free(struct nfcsim_link *link)
  80 {
  81         dev_kfree_skb(link->skb);
  82         kfree(link);
  83 }
  84 
  85 static void nfcsim_link_recv_wake(struct nfcsim_link *link)
  86 {
  87         link->cond = 1;
  88         wake_up_interruptible(&link->recv_wait);
  89 }
  90 
  91 static void nfcsim_link_set_skb(struct nfcsim_link *link, struct sk_buff *skb,
  92                                 u8 rf_tech, u8 mode)
  93 {
  94         mutex_lock(&link->lock);
  95 
  96         dev_kfree_skb(link->skb);
  97         link->skb = skb;
  98         link->rf_tech = rf_tech;
  99         link->mode = mode;
 100 
 101         mutex_unlock(&link->lock);
 102 }
 103 
 104 static void nfcsim_link_recv_cancel(struct nfcsim_link *link)
 105 {
 106         mutex_lock(&link->lock);
 107 
 108         link->mode = NFCSIM_MODE_NONE;
 109 
 110         mutex_unlock(&link->lock);
 111 
 112         nfcsim_link_recv_wake(link);
 113 }
 114 
 115 static void nfcsim_link_shutdown(struct nfcsim_link *link)
 116 {
 117         mutex_lock(&link->lock);
 118 
 119         link->shutdown = 1;
 120         link->mode = NFCSIM_MODE_NONE;
 121 
 122         mutex_unlock(&link->lock);
 123 
 124         nfcsim_link_recv_wake(link);
 125 }
 126 
 127 static struct sk_buff *nfcsim_link_recv_skb(struct nfcsim_link *link,
 128                                             int timeout, u8 rf_tech, u8 mode)
 129 {
 130         int rc;
 131         struct sk_buff *skb;
 132 
 133         rc = wait_event_interruptible_timeout(link->recv_wait,
 134                                               link->cond,
 135                                               msecs_to_jiffies(timeout));
 136 
 137         mutex_lock(&link->lock);
 138 
 139         skb = link->skb;
 140         link->skb = NULL;
 141 
 142         if (!rc) {
 143                 rc = -ETIMEDOUT;
 144                 goto done;
 145         }
 146 
 147         if (!skb || link->rf_tech != rf_tech || link->mode == mode) {
 148                 rc = -EINVAL;
 149                 goto done;
 150         }
 151 
 152         if (link->shutdown) {
 153                 rc = -ENODEV;
 154                 goto done;
 155         }
 156 
 157 done:
 158         mutex_unlock(&link->lock);
 159 
 160         if (rc < 0) {
 161                 dev_kfree_skb(skb);
 162                 skb = ERR_PTR(rc);
 163         }
 164 
 165         link->cond = 0;
 166 
 167         return skb;
 168 }
 169 
 170 static void nfcsim_send_wq(struct work_struct *work)
 171 {
 172         struct nfcsim *dev = container_of(work, struct nfcsim, send_work.work);
 173 
 174         /*
 175          * To effectively send data, the device just wake up its link_out which
 176          * is the link_in of the peer device. The exchanged skb has already been
 177          * stored in the dev->link_out through nfcsim_link_set_skb().
 178          */
 179         nfcsim_link_recv_wake(dev->link_out);
 180 }
 181 
 182 static void nfcsim_recv_wq(struct work_struct *work)
 183 {
 184         struct nfcsim *dev = container_of(work, struct nfcsim, recv_work);
 185         struct sk_buff *skb;
 186 
 187         skb = nfcsim_link_recv_skb(dev->link_in, dev->recv_timeout,
 188                                    dev->rf_tech, dev->mode);
 189 
 190         if (!dev->up) {
 191                 NFCSIM_ERR(dev, "Device is down\n");
 192 
 193                 if (!IS_ERR(skb))
 194                         dev_kfree_skb(skb);
 195 
 196                 skb = ERR_PTR(-ENODEV);
 197         }
 198 
 199         dev->cb(dev->nfc_digital_dev, dev->arg, skb);
 200 }
 201 
 202 static int nfcsim_send(struct nfc_digital_dev *ddev, struct sk_buff *skb,
 203                        u16 timeout, nfc_digital_cmd_complete_t cb, void *arg)
 204 {
 205         struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
 206         u8 delay;
 207 
 208         if (!dev->up) {
 209                 NFCSIM_ERR(dev, "Device is down\n");
 210                 return -ENODEV;
 211         }
 212 
 213         dev->recv_timeout = timeout;
 214         dev->cb = cb;
 215         dev->arg = arg;
 216 
 217         schedule_work(&dev->recv_work);
 218 
 219         if (dev->dropframe) {
 220                 NFCSIM_DBG(dev, "dropping frame (out of %d)\n", dev->dropframe);
 221                 dev_kfree_skb(skb);
 222                 dev->dropframe--;
 223 
 224                 return 0;
 225         }
 226 
 227         if (skb) {
 228                 nfcsim_link_set_skb(dev->link_out, skb, dev->rf_tech,
 229                                     dev->mode);
 230 
 231                 /* Add random delay (between 3 and 10 ms) before sending data */
 232                 get_random_bytes(&delay, 1);
 233                 delay = 3 + (delay & 0x07);
 234 
 235                 schedule_delayed_work(&dev->send_work, msecs_to_jiffies(delay));
 236         }
 237 
 238         return 0;
 239 }
 240 
 241 static void nfcsim_abort_cmd(struct nfc_digital_dev *ddev)
 242 {
 243         struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
 244 
 245         nfcsim_link_recv_cancel(dev->link_in);
 246 }
 247 
 248 static int nfcsim_switch_rf(struct nfc_digital_dev *ddev, bool on)
 249 {
 250         struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
 251 
 252         dev->up = on;
 253 
 254         return 0;
 255 }
 256 
 257 static int nfcsim_in_configure_hw(struct nfc_digital_dev *ddev,
 258                                           int type, int param)
 259 {
 260         struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
 261 
 262         switch (type) {
 263         case NFC_DIGITAL_CONFIG_RF_TECH:
 264                 dev->up = true;
 265                 dev->mode = NFCSIM_MODE_INITIATOR;
 266                 dev->rf_tech = param;
 267                 break;
 268 
 269         case NFC_DIGITAL_CONFIG_FRAMING:
 270                 break;
 271 
 272         default:
 273                 NFCSIM_ERR(dev, "Invalid configuration type: %d\n", type);
 274                 return -EINVAL;
 275         }
 276 
 277         return 0;
 278 }
 279 
 280 static int nfcsim_in_send_cmd(struct nfc_digital_dev *ddev,
 281                                struct sk_buff *skb, u16 timeout,
 282                                nfc_digital_cmd_complete_t cb, void *arg)
 283 {
 284         return nfcsim_send(ddev, skb, timeout, cb, arg);
 285 }
 286 
 287 static int nfcsim_tg_configure_hw(struct nfc_digital_dev *ddev,
 288                                           int type, int param)
 289 {
 290         struct nfcsim *dev = nfc_digital_get_drvdata(ddev);
 291 
 292         switch (type) {
 293         case NFC_DIGITAL_CONFIG_RF_TECH:
 294                 dev->up = true;
 295                 dev->mode = NFCSIM_MODE_TARGET;
 296                 dev->rf_tech = param;
 297                 break;
 298 
 299         case NFC_DIGITAL_CONFIG_FRAMING:
 300                 break;
 301 
 302         default:
 303                 NFCSIM_ERR(dev, "Invalid configuration type: %d\n", type);
 304                 return -EINVAL;
 305         }
 306 
 307         return 0;
 308 }
 309 
 310 static int nfcsim_tg_send_cmd(struct nfc_digital_dev *ddev,
 311                                struct sk_buff *skb, u16 timeout,
 312                                nfc_digital_cmd_complete_t cb, void *arg)
 313 {
 314         return nfcsim_send(ddev, skb, timeout, cb, arg);
 315 }
 316 
 317 static int nfcsim_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
 318                             nfc_digital_cmd_complete_t cb, void *arg)
 319 {
 320         return nfcsim_send(ddev, NULL, timeout, cb, arg);
 321 }
 322 
 323 static struct nfc_digital_ops nfcsim_digital_ops = {
 324         .in_configure_hw = nfcsim_in_configure_hw,
 325         .in_send_cmd = nfcsim_in_send_cmd,
 326 
 327         .tg_listen = nfcsim_tg_listen,
 328         .tg_configure_hw = nfcsim_tg_configure_hw,
 329         .tg_send_cmd = nfcsim_tg_send_cmd,
 330 
 331         .abort_cmd = nfcsim_abort_cmd,
 332         .switch_rf = nfcsim_switch_rf,
 333 };
 334 
 335 static struct dentry *nfcsim_debugfs_root;
 336 
 337 static void nfcsim_debugfs_init(void)
 338 {
 339         nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
 340 
 341         if (!nfcsim_debugfs_root)
 342                 pr_err("Could not create debugfs entry\n");
 343 
 344 }
 345 
 346 static void nfcsim_debugfs_remove(void)
 347 {
 348         debugfs_remove_recursive(nfcsim_debugfs_root);
 349 }
 350 
 351 static void nfcsim_debugfs_init_dev(struct nfcsim *dev)
 352 {
 353         struct dentry *dev_dir;
 354         char devname[5]; /* nfcX\0 */
 355         u32 idx;
 356         int n;
 357 
 358         if (!nfcsim_debugfs_root) {
 359                 NFCSIM_ERR(dev, "nfcsim debugfs not initialized\n");
 360                 return;
 361         }
 362 
 363         idx = dev->nfc_digital_dev->nfc_dev->idx;
 364         n = snprintf(devname, sizeof(devname), "nfc%d", idx);
 365         if (n >= sizeof(devname)) {
 366                 NFCSIM_ERR(dev, "Could not compute dev name for dev %d\n", idx);
 367                 return;
 368         }
 369 
 370         dev_dir = debugfs_create_dir(devname, nfcsim_debugfs_root);
 371         if (!dev_dir) {
 372                 NFCSIM_ERR(dev, "Could not create debugfs entries for nfc%d\n",
 373                            idx);
 374                 return;
 375         }
 376 
 377         debugfs_create_u8("dropframe", 0664, dev_dir, &dev->dropframe);
 378 }
 379 
 380 static struct nfcsim *nfcsim_device_new(struct nfcsim_link *link_in,
 381                                         struct nfcsim_link *link_out)
 382 {
 383         struct nfcsim *dev;
 384         int rc;
 385 
 386         dev = kzalloc(sizeof(struct nfcsim), GFP_KERNEL);
 387         if (!dev)
 388                 return ERR_PTR(-ENOMEM);
 389 
 390         INIT_DELAYED_WORK(&dev->send_work, nfcsim_send_wq);
 391         INIT_WORK(&dev->recv_work, nfcsim_recv_wq);
 392 
 393         dev->nfc_digital_dev =
 394                         nfc_digital_allocate_device(&nfcsim_digital_ops,
 395                                                     NFC_PROTO_NFC_DEP_MASK,
 396                                                     NFCSIM_CAPABILITIES,
 397                                                     0, 0);
 398         if (!dev->nfc_digital_dev) {
 399                 kfree(dev);
 400                 return ERR_PTR(-ENOMEM);
 401         }
 402 
 403         nfc_digital_set_drvdata(dev->nfc_digital_dev, dev);
 404 
 405         dev->link_in = link_in;
 406         dev->link_out = link_out;
 407 
 408         rc = nfc_digital_register_device(dev->nfc_digital_dev);
 409         if (rc) {
 410                 pr_err("Could not register digital device (%d)\n", rc);
 411                 nfc_digital_free_device(dev->nfc_digital_dev);
 412                 kfree(dev);
 413 
 414                 return ERR_PTR(rc);
 415         }
 416 
 417         nfcsim_debugfs_init_dev(dev);
 418 
 419         return dev;
 420 }
 421 
 422 static void nfcsim_device_free(struct nfcsim *dev)
 423 {
 424         nfc_digital_unregister_device(dev->nfc_digital_dev);
 425 
 426         dev->up = false;
 427 
 428         nfcsim_link_shutdown(dev->link_in);
 429 
 430         cancel_delayed_work_sync(&dev->send_work);
 431         cancel_work_sync(&dev->recv_work);
 432 
 433         nfc_digital_free_device(dev->nfc_digital_dev);
 434 
 435         kfree(dev);
 436 }
 437 
 438 static struct nfcsim *dev0;
 439 static struct nfcsim *dev1;
 440 
 441 static int __init nfcsim_init(void)
 442 {
 443         struct nfcsim_link *link0, *link1;
 444         int rc;
 445 
 446         link0 = nfcsim_link_new();
 447         link1 = nfcsim_link_new();
 448         if (!link0 || !link1) {
 449                 rc = -ENOMEM;
 450                 goto exit_err;
 451         }
 452 
 453         nfcsim_debugfs_init();
 454 
 455         dev0 = nfcsim_device_new(link0, link1);
 456         if (IS_ERR(dev0)) {
 457                 rc = PTR_ERR(dev0);
 458                 goto exit_err;
 459         }
 460 
 461         dev1 = nfcsim_device_new(link1, link0);
 462         if (IS_ERR(dev1)) {
 463                 nfcsim_device_free(dev0);
 464 
 465                 rc = PTR_ERR(dev1);
 466                 goto exit_err;
 467         }
 468 
 469         pr_info("nfcsim " NFCSIM_VERSION " initialized\n");
 470 
 471         return 0;
 472 
 473 exit_err:
 474         pr_err("Failed to initialize nfcsim driver (%d)\n", rc);
 475 
 476         if (link0)
 477                 nfcsim_link_free(link0);
 478         if (link1)
 479                 nfcsim_link_free(link1);
 480 
 481         return rc;
 482 }
 483 
 484 static void __exit nfcsim_exit(void)
 485 {
 486         struct nfcsim_link *link0, *link1;
 487 
 488         link0 = dev0->link_in;
 489         link1 = dev0->link_out;
 490 
 491         nfcsim_device_free(dev0);
 492         nfcsim_device_free(dev1);
 493 
 494         nfcsim_link_free(link0);
 495         nfcsim_link_free(link1);
 496 
 497         nfcsim_debugfs_remove();
 498 }
 499 
 500 module_init(nfcsim_init);
 501 module_exit(nfcsim_exit);
 502 
 503 MODULE_DESCRIPTION("NFCSim driver ver " NFCSIM_VERSION);
 504 MODULE_VERSION(NFCSIM_VERSION);
 505 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */