17cbe0ff3SThierry Escande /* 27cbe0ff3SThierry Escande * NFC hardware simulation driver 37cbe0ff3SThierry Escande * Copyright (c) 2013, Intel Corporation. 47cbe0ff3SThierry Escande * 57cbe0ff3SThierry Escande * This program is free software; you can redistribute it and/or modify it 67cbe0ff3SThierry Escande * under the terms and conditions of the GNU General Public License, 77cbe0ff3SThierry Escande * version 2, as published by the Free Software Foundation. 87cbe0ff3SThierry Escande * 97cbe0ff3SThierry Escande * This program is distributed in the hope it will be useful, but WITHOUT 107cbe0ff3SThierry Escande * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 117cbe0ff3SThierry Escande * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 127cbe0ff3SThierry Escande * more details. 137cbe0ff3SThierry Escande * 147cbe0ff3SThierry Escande */ 157cbe0ff3SThierry Escande 167cbe0ff3SThierry Escande #include <linux/device.h> 177cbe0ff3SThierry Escande #include <linux/kernel.h> 187cbe0ff3SThierry Escande #include <linux/module.h> 197cbe0ff3SThierry Escande #include <linux/nfc.h> 207cbe0ff3SThierry Escande #include <net/nfc/nfc.h> 217cbe0ff3SThierry Escande 227cbe0ff3SThierry Escande #define DEV_ERR(_dev, fmt, args...) nfc_dev_err(&_dev->nfc_dev->dev, \ 237cbe0ff3SThierry Escande "%s: " fmt, __func__, ## args) 247cbe0ff3SThierry Escande 257cbe0ff3SThierry Escande #define DEV_DBG(_dev, fmt, args...) nfc_dev_dbg(&_dev->nfc_dev->dev, \ 267cbe0ff3SThierry Escande "%s: " fmt, __func__, ## args) 277cbe0ff3SThierry Escande 287cbe0ff3SThierry Escande #define NFCSIM_VERSION "0.1" 297cbe0ff3SThierry Escande 307cbe0ff3SThierry Escande #define NFCSIM_POLL_NONE 0 317cbe0ff3SThierry Escande #define NFCSIM_POLL_INITIATOR 1 327cbe0ff3SThierry Escande #define NFCSIM_POLL_TARGET 2 337cbe0ff3SThierry Escande #define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET) 347cbe0ff3SThierry Escande 357cbe0ff3SThierry Escande struct nfcsim { 367cbe0ff3SThierry Escande struct nfc_dev *nfc_dev; 377cbe0ff3SThierry Escande 387cbe0ff3SThierry Escande struct mutex lock; 397cbe0ff3SThierry Escande 407cbe0ff3SThierry Escande struct delayed_work recv_work; 417cbe0ff3SThierry Escande 427cbe0ff3SThierry Escande struct sk_buff *clone_skb; 437cbe0ff3SThierry Escande 447cbe0ff3SThierry Escande struct delayed_work poll_work; 457cbe0ff3SThierry Escande u8 polling_mode; 467cbe0ff3SThierry Escande u8 curr_polling_mode; 477cbe0ff3SThierry Escande 487cbe0ff3SThierry Escande u8 shutting_down; 497cbe0ff3SThierry Escande 507cbe0ff3SThierry Escande u8 up; 517cbe0ff3SThierry Escande 527cbe0ff3SThierry Escande u8 initiator; 537cbe0ff3SThierry Escande 547cbe0ff3SThierry Escande data_exchange_cb_t cb; 557cbe0ff3SThierry Escande void *cb_context; 567cbe0ff3SThierry Escande 577cbe0ff3SThierry Escande struct nfcsim *peer_dev; 587cbe0ff3SThierry Escande }; 597cbe0ff3SThierry Escande 607cbe0ff3SThierry Escande static struct nfcsim *dev0; 617cbe0ff3SThierry Escande static struct nfcsim *dev1; 627cbe0ff3SThierry Escande 63*40dac370SThierry Escande static struct workqueue_struct *wq; 647cbe0ff3SThierry Escande 657cbe0ff3SThierry Escande static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) 667cbe0ff3SThierry Escande { 677cbe0ff3SThierry Escande DEV_DBG(dev, "shutdown=%d", shutdown); 687cbe0ff3SThierry Escande 697cbe0ff3SThierry Escande mutex_lock(&dev->lock); 707cbe0ff3SThierry Escande 717cbe0ff3SThierry Escande dev->polling_mode = NFCSIM_POLL_NONE; 727cbe0ff3SThierry Escande dev->shutting_down = shutdown; 737cbe0ff3SThierry Escande dev->cb = NULL; 747cbe0ff3SThierry Escande dev_kfree_skb(dev->clone_skb); 757cbe0ff3SThierry Escande dev->clone_skb = NULL; 767cbe0ff3SThierry Escande 777cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 787cbe0ff3SThierry Escande 797cbe0ff3SThierry Escande cancel_delayed_work_sync(&dev->poll_work); 807cbe0ff3SThierry Escande cancel_delayed_work_sync(&dev->recv_work); 817cbe0ff3SThierry Escande } 827cbe0ff3SThierry Escande 837cbe0ff3SThierry Escande static int nfcsim_target_found(struct nfcsim *dev) 847cbe0ff3SThierry Escande { 857cbe0ff3SThierry Escande struct nfc_target nfc_tgt; 867cbe0ff3SThierry Escande 877cbe0ff3SThierry Escande DEV_DBG(dev, ""); 887cbe0ff3SThierry Escande 897cbe0ff3SThierry Escande memset(&nfc_tgt, 0, sizeof(struct nfc_target)); 907cbe0ff3SThierry Escande 917cbe0ff3SThierry Escande nfc_tgt.supported_protocols = NFC_PROTO_NFC_DEP_MASK; 927cbe0ff3SThierry Escande nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); 937cbe0ff3SThierry Escande 947cbe0ff3SThierry Escande return 0; 957cbe0ff3SThierry Escande } 967cbe0ff3SThierry Escande 977cbe0ff3SThierry Escande static int nfcsim_dev_up(struct nfc_dev *nfc_dev) 987cbe0ff3SThierry Escande { 997cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 1007cbe0ff3SThierry Escande 1017cbe0ff3SThierry Escande DEV_DBG(dev, ""); 1027cbe0ff3SThierry Escande 1037cbe0ff3SThierry Escande mutex_lock(&dev->lock); 1047cbe0ff3SThierry Escande 1057cbe0ff3SThierry Escande dev->up = 1; 1067cbe0ff3SThierry Escande 1077cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 1087cbe0ff3SThierry Escande 1097cbe0ff3SThierry Escande return 0; 1107cbe0ff3SThierry Escande } 1117cbe0ff3SThierry Escande 1127cbe0ff3SThierry Escande static int nfcsim_dev_down(struct nfc_dev *nfc_dev) 1137cbe0ff3SThierry Escande { 1147cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 1157cbe0ff3SThierry Escande 1167cbe0ff3SThierry Escande DEV_DBG(dev, ""); 1177cbe0ff3SThierry Escande 1187cbe0ff3SThierry Escande mutex_lock(&dev->lock); 1197cbe0ff3SThierry Escande 1207cbe0ff3SThierry Escande dev->up = 0; 1217cbe0ff3SThierry Escande 1227cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 1237cbe0ff3SThierry Escande 1247cbe0ff3SThierry Escande return 0; 1257cbe0ff3SThierry Escande } 1267cbe0ff3SThierry Escande 1277cbe0ff3SThierry Escande static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, 1287cbe0ff3SThierry Escande struct nfc_target *target, 1297cbe0ff3SThierry Escande u8 comm_mode, u8 *gb, size_t gb_len) 1307cbe0ff3SThierry Escande { 1317cbe0ff3SThierry Escande int rc; 1327cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 1337cbe0ff3SThierry Escande struct nfcsim *peer = dev->peer_dev; 1347cbe0ff3SThierry Escande u8 *remote_gb; 1357cbe0ff3SThierry Escande size_t remote_gb_len; 1367cbe0ff3SThierry Escande 1377cbe0ff3SThierry Escande DEV_DBG(dev, "target_idx: %d, comm_mode: %d\n", target->idx, comm_mode); 1387cbe0ff3SThierry Escande 1397cbe0ff3SThierry Escande mutex_lock(&peer->lock); 1407cbe0ff3SThierry Escande 1417cbe0ff3SThierry Escande nfc_tm_activated(peer->nfc_dev, NFC_PROTO_NFC_DEP_MASK, 1427cbe0ff3SThierry Escande NFC_COMM_ACTIVE, gb, gb_len); 1437cbe0ff3SThierry Escande 1447cbe0ff3SThierry Escande remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); 1457cbe0ff3SThierry Escande if (!remote_gb) { 1467cbe0ff3SThierry Escande DEV_ERR(peer, "Can't get remote general bytes"); 1477cbe0ff3SThierry Escande 1487cbe0ff3SThierry Escande mutex_unlock(&peer->lock); 1497cbe0ff3SThierry Escande return -EINVAL; 1507cbe0ff3SThierry Escande } 1517cbe0ff3SThierry Escande 1527cbe0ff3SThierry Escande mutex_unlock(&peer->lock); 1537cbe0ff3SThierry Escande 1547cbe0ff3SThierry Escande mutex_lock(&dev->lock); 1557cbe0ff3SThierry Escande 1567cbe0ff3SThierry Escande rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); 1577cbe0ff3SThierry Escande if (rc) { 1587cbe0ff3SThierry Escande DEV_ERR(dev, "Can't set remote general bytes"); 1597cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 1607cbe0ff3SThierry Escande return rc; 1617cbe0ff3SThierry Escande } 1627cbe0ff3SThierry Escande 1637cbe0ff3SThierry Escande rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_ACTIVE, 1647cbe0ff3SThierry Escande NFC_RF_INITIATOR); 1657cbe0ff3SThierry Escande 1667cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 1677cbe0ff3SThierry Escande 1687cbe0ff3SThierry Escande return rc; 1697cbe0ff3SThierry Escande } 1707cbe0ff3SThierry Escande 1717cbe0ff3SThierry Escande static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) 1727cbe0ff3SThierry Escande { 1737cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 1747cbe0ff3SThierry Escande 1757cbe0ff3SThierry Escande DEV_DBG(dev, ""); 1767cbe0ff3SThierry Escande 1777cbe0ff3SThierry Escande nfcsim_cleanup_dev(dev, 0); 1787cbe0ff3SThierry Escande 1797cbe0ff3SThierry Escande return 0; 1807cbe0ff3SThierry Escande } 1817cbe0ff3SThierry Escande 1827cbe0ff3SThierry Escande static int nfcsim_start_poll(struct nfc_dev *nfc_dev, 1837cbe0ff3SThierry Escande u32 im_protocols, u32 tm_protocols) 1847cbe0ff3SThierry Escande { 1857cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 1867cbe0ff3SThierry Escande int rc; 1877cbe0ff3SThierry Escande 1887cbe0ff3SThierry Escande mutex_lock(&dev->lock); 1897cbe0ff3SThierry Escande 1907cbe0ff3SThierry Escande if (dev->polling_mode != NFCSIM_POLL_NONE) { 1917cbe0ff3SThierry Escande DEV_ERR(dev, "Already in polling mode"); 1927cbe0ff3SThierry Escande rc = -EBUSY; 1937cbe0ff3SThierry Escande goto exit; 1947cbe0ff3SThierry Escande } 1957cbe0ff3SThierry Escande 1967cbe0ff3SThierry Escande if (im_protocols & NFC_PROTO_NFC_DEP_MASK) 1977cbe0ff3SThierry Escande dev->polling_mode |= NFCSIM_POLL_INITIATOR; 1987cbe0ff3SThierry Escande 1997cbe0ff3SThierry Escande if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) 2007cbe0ff3SThierry Escande dev->polling_mode |= NFCSIM_POLL_TARGET; 2017cbe0ff3SThierry Escande 2027cbe0ff3SThierry Escande if (dev->polling_mode == NFCSIM_POLL_NONE) { 2037cbe0ff3SThierry Escande DEV_ERR(dev, "Unsupported polling mode"); 2047cbe0ff3SThierry Escande rc = -EINVAL; 2057cbe0ff3SThierry Escande goto exit; 2067cbe0ff3SThierry Escande } 2077cbe0ff3SThierry Escande 2087cbe0ff3SThierry Escande dev->initiator = 0; 2097cbe0ff3SThierry Escande dev->curr_polling_mode = NFCSIM_POLL_NONE; 2107cbe0ff3SThierry Escande 2117cbe0ff3SThierry Escande queue_delayed_work(wq, &dev->poll_work, 0); 2127cbe0ff3SThierry Escande 2137cbe0ff3SThierry Escande DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X", im_protocols, 2147cbe0ff3SThierry Escande tm_protocols); 2157cbe0ff3SThierry Escande 2167cbe0ff3SThierry Escande rc = 0; 2177cbe0ff3SThierry Escande exit: 2187cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 2197cbe0ff3SThierry Escande 2207cbe0ff3SThierry Escande return rc; 2217cbe0ff3SThierry Escande } 2227cbe0ff3SThierry Escande 2237cbe0ff3SThierry Escande static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) 2247cbe0ff3SThierry Escande { 2257cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 2267cbe0ff3SThierry Escande 2277cbe0ff3SThierry Escande DEV_DBG(dev, "Stop poll"); 2287cbe0ff3SThierry Escande 2297cbe0ff3SThierry Escande mutex_lock(&dev->lock); 2307cbe0ff3SThierry Escande 2317cbe0ff3SThierry Escande dev->polling_mode = NFCSIM_POLL_NONE; 2327cbe0ff3SThierry Escande 2337cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 2347cbe0ff3SThierry Escande 2357cbe0ff3SThierry Escande cancel_delayed_work_sync(&dev->poll_work); 2367cbe0ff3SThierry Escande } 2377cbe0ff3SThierry Escande 2387cbe0ff3SThierry Escande static int nfcsim_activate_target(struct nfc_dev *nfc_dev, 2397cbe0ff3SThierry Escande struct nfc_target *target, u32 protocol) 2407cbe0ff3SThierry Escande { 2417cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 2427cbe0ff3SThierry Escande 2437cbe0ff3SThierry Escande DEV_DBG(dev, ""); 2447cbe0ff3SThierry Escande 2457cbe0ff3SThierry Escande return -ENOTSUPP; 2467cbe0ff3SThierry Escande } 2477cbe0ff3SThierry Escande 2487cbe0ff3SThierry Escande static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, 2497cbe0ff3SThierry Escande struct nfc_target *target) 2507cbe0ff3SThierry Escande { 2517cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 2527cbe0ff3SThierry Escande 2537cbe0ff3SThierry Escande DEV_DBG(dev, ""); 2547cbe0ff3SThierry Escande } 2557cbe0ff3SThierry Escande 2567cbe0ff3SThierry Escande static void nfcsim_wq_recv(struct work_struct *work) 2577cbe0ff3SThierry Escande { 2587cbe0ff3SThierry Escande struct nfcsim *dev = container_of(work, struct nfcsim, 2597cbe0ff3SThierry Escande recv_work.work); 2607cbe0ff3SThierry Escande 2617cbe0ff3SThierry Escande mutex_lock(&dev->lock); 2627cbe0ff3SThierry Escande 2637cbe0ff3SThierry Escande if (dev->shutting_down || !dev->up || !dev->clone_skb) { 2647cbe0ff3SThierry Escande dev_kfree_skb(dev->clone_skb); 2657cbe0ff3SThierry Escande goto exit; 2667cbe0ff3SThierry Escande } 2677cbe0ff3SThierry Escande 2687cbe0ff3SThierry Escande if (dev->initiator) { 2697cbe0ff3SThierry Escande if (!dev->cb) { 2707cbe0ff3SThierry Escande DEV_ERR(dev, "Null recv callback"); 2717cbe0ff3SThierry Escande dev_kfree_skb(dev->clone_skb); 2727cbe0ff3SThierry Escande goto exit; 2737cbe0ff3SThierry Escande } 2747cbe0ff3SThierry Escande 2757cbe0ff3SThierry Escande dev->cb(dev->cb_context, dev->clone_skb, 0); 2767cbe0ff3SThierry Escande dev->cb = NULL; 2777cbe0ff3SThierry Escande } else { 2787cbe0ff3SThierry Escande nfc_tm_data_received(dev->nfc_dev, dev->clone_skb); 2797cbe0ff3SThierry Escande } 2807cbe0ff3SThierry Escande 2817cbe0ff3SThierry Escande exit: 2827cbe0ff3SThierry Escande dev->clone_skb = NULL; 2837cbe0ff3SThierry Escande 2847cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 2857cbe0ff3SThierry Escande } 2867cbe0ff3SThierry Escande 2877cbe0ff3SThierry Escande static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, 2887cbe0ff3SThierry Escande struct sk_buff *skb, data_exchange_cb_t cb, 2897cbe0ff3SThierry Escande void *cb_context) 2907cbe0ff3SThierry Escande { 2917cbe0ff3SThierry Escande struct nfcsim *dev = nfc_get_drvdata(nfc_dev); 2927cbe0ff3SThierry Escande struct nfcsim *peer = dev->peer_dev; 2937cbe0ff3SThierry Escande int err; 2947cbe0ff3SThierry Escande 2957cbe0ff3SThierry Escande mutex_lock(&dev->lock); 2967cbe0ff3SThierry Escande 2977cbe0ff3SThierry Escande if (dev->shutting_down || !dev->up) { 2987cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 2997cbe0ff3SThierry Escande err = -ENODEV; 3007cbe0ff3SThierry Escande goto exit; 3017cbe0ff3SThierry Escande } 3027cbe0ff3SThierry Escande 3037cbe0ff3SThierry Escande dev->cb = cb; 3047cbe0ff3SThierry Escande dev->cb_context = cb_context; 3057cbe0ff3SThierry Escande 3067cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 3077cbe0ff3SThierry Escande 3087cbe0ff3SThierry Escande mutex_lock(&peer->lock); 3097cbe0ff3SThierry Escande 3107cbe0ff3SThierry Escande peer->clone_skb = skb_clone(skb, GFP_KERNEL); 3117cbe0ff3SThierry Escande 3127cbe0ff3SThierry Escande if (!peer->clone_skb) { 3137cbe0ff3SThierry Escande DEV_ERR(dev, "skb_clone failed"); 3147cbe0ff3SThierry Escande mutex_unlock(&peer->lock); 3157cbe0ff3SThierry Escande err = -ENOMEM; 3167cbe0ff3SThierry Escande goto exit; 3177cbe0ff3SThierry Escande } 3187cbe0ff3SThierry Escande 3197cbe0ff3SThierry Escande /* This simulates an arbitrary transmission delay between the 2 devices. 3207cbe0ff3SThierry Escande * If packet transmission occurs immediately between them, we have a 3217cbe0ff3SThierry Escande * non-stop flow of several tens of thousands SYMM packets per second 3227cbe0ff3SThierry Escande * and a burning cpu. 3237cbe0ff3SThierry Escande * 3247cbe0ff3SThierry Escande * TODO: Add support for a sysfs entry to control this delay. 3257cbe0ff3SThierry Escande */ 3267cbe0ff3SThierry Escande queue_delayed_work(wq, &peer->recv_work, msecs_to_jiffies(5)); 3277cbe0ff3SThierry Escande 3287cbe0ff3SThierry Escande mutex_unlock(&peer->lock); 3297cbe0ff3SThierry Escande 3307cbe0ff3SThierry Escande err = 0; 3317cbe0ff3SThierry Escande exit: 3327cbe0ff3SThierry Escande dev_kfree_skb(skb); 3337cbe0ff3SThierry Escande 3347cbe0ff3SThierry Escande return err; 3357cbe0ff3SThierry Escande } 3367cbe0ff3SThierry Escande 3377cbe0ff3SThierry Escande static int nfcsim_im_transceive(struct nfc_dev *nfc_dev, 3387cbe0ff3SThierry Escande struct nfc_target *target, struct sk_buff *skb, 3397cbe0ff3SThierry Escande data_exchange_cb_t cb, void *cb_context) 3407cbe0ff3SThierry Escande { 3417cbe0ff3SThierry Escande return nfcsim_tx(nfc_dev, target, skb, cb, cb_context); 3427cbe0ff3SThierry Escande } 3437cbe0ff3SThierry Escande 3447cbe0ff3SThierry Escande static int nfcsim_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) 3457cbe0ff3SThierry Escande { 3467cbe0ff3SThierry Escande return nfcsim_tx(nfc_dev, NULL, skb, NULL, NULL); 3477cbe0ff3SThierry Escande } 3487cbe0ff3SThierry Escande 3497cbe0ff3SThierry Escande static struct nfc_ops nfcsim_nfc_ops = { 3507cbe0ff3SThierry Escande .dev_up = nfcsim_dev_up, 3517cbe0ff3SThierry Escande .dev_down = nfcsim_dev_down, 3527cbe0ff3SThierry Escande .dep_link_up = nfcsim_dep_link_up, 3537cbe0ff3SThierry Escande .dep_link_down = nfcsim_dep_link_down, 3547cbe0ff3SThierry Escande .start_poll = nfcsim_start_poll, 3557cbe0ff3SThierry Escande .stop_poll = nfcsim_stop_poll, 3567cbe0ff3SThierry Escande .activate_target = nfcsim_activate_target, 3577cbe0ff3SThierry Escande .deactivate_target = nfcsim_deactivate_target, 3587cbe0ff3SThierry Escande .im_transceive = nfcsim_im_transceive, 3597cbe0ff3SThierry Escande .tm_send = nfcsim_tm_send, 3607cbe0ff3SThierry Escande }; 3617cbe0ff3SThierry Escande 3627cbe0ff3SThierry Escande static void nfcsim_set_polling_mode(struct nfcsim *dev) 3637cbe0ff3SThierry Escande { 3647cbe0ff3SThierry Escande if (dev->polling_mode == NFCSIM_POLL_NONE) { 3657cbe0ff3SThierry Escande dev->curr_polling_mode = NFCSIM_POLL_NONE; 3667cbe0ff3SThierry Escande return; 3677cbe0ff3SThierry Escande } 3687cbe0ff3SThierry Escande 3697cbe0ff3SThierry Escande if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { 3707cbe0ff3SThierry Escande if (dev->polling_mode & NFCSIM_POLL_INITIATOR) 3717cbe0ff3SThierry Escande dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; 3727cbe0ff3SThierry Escande else 3737cbe0ff3SThierry Escande dev->curr_polling_mode = NFCSIM_POLL_TARGET; 3747cbe0ff3SThierry Escande 3757cbe0ff3SThierry Escande return; 3767cbe0ff3SThierry Escande } 3777cbe0ff3SThierry Escande 3787cbe0ff3SThierry Escande if (dev->polling_mode == NFCSIM_POLL_DUAL) { 3797cbe0ff3SThierry Escande if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) 3807cbe0ff3SThierry Escande dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; 3817cbe0ff3SThierry Escande else 3827cbe0ff3SThierry Escande dev->curr_polling_mode = NFCSIM_POLL_TARGET; 3837cbe0ff3SThierry Escande } 3847cbe0ff3SThierry Escande } 3857cbe0ff3SThierry Escande 3867cbe0ff3SThierry Escande static void nfcsim_wq_poll(struct work_struct *work) 3877cbe0ff3SThierry Escande { 3887cbe0ff3SThierry Escande struct nfcsim *dev = container_of(work, struct nfcsim, poll_work.work); 3897cbe0ff3SThierry Escande struct nfcsim *peer = dev->peer_dev; 3907cbe0ff3SThierry Escande 3917cbe0ff3SThierry Escande /* These work items run on an ordered workqueue and are therefore 3927cbe0ff3SThierry Escande * serialized. So we can take both mutexes without being dead locked. 3937cbe0ff3SThierry Escande */ 3947cbe0ff3SThierry Escande mutex_lock(&dev->lock); 3957cbe0ff3SThierry Escande mutex_lock(&peer->lock); 3967cbe0ff3SThierry Escande 3977cbe0ff3SThierry Escande nfcsim_set_polling_mode(dev); 3987cbe0ff3SThierry Escande 3997cbe0ff3SThierry Escande if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { 4007cbe0ff3SThierry Escande DEV_DBG(dev, "Not polling"); 4017cbe0ff3SThierry Escande goto unlock; 4027cbe0ff3SThierry Escande } 4037cbe0ff3SThierry Escande 4047cbe0ff3SThierry Escande DEV_DBG(dev, "Polling as %s", 4057cbe0ff3SThierry Escande dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? 4067cbe0ff3SThierry Escande "initiator" : "target"); 4077cbe0ff3SThierry Escande 4087cbe0ff3SThierry Escande if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) 4097cbe0ff3SThierry Escande goto sched_work; 4107cbe0ff3SThierry Escande 4117cbe0ff3SThierry Escande if (peer->curr_polling_mode == NFCSIM_POLL_TARGET) { 4127cbe0ff3SThierry Escande peer->polling_mode = NFCSIM_POLL_NONE; 4137cbe0ff3SThierry Escande dev->polling_mode = NFCSIM_POLL_NONE; 4147cbe0ff3SThierry Escande 4157cbe0ff3SThierry Escande dev->initiator = 1; 4167cbe0ff3SThierry Escande 4177cbe0ff3SThierry Escande nfcsim_target_found(dev); 4187cbe0ff3SThierry Escande 4197cbe0ff3SThierry Escande goto unlock; 4207cbe0ff3SThierry Escande } 4217cbe0ff3SThierry Escande 4227cbe0ff3SThierry Escande sched_work: 4237cbe0ff3SThierry Escande /* This defines the delay for an initiator to check if the other device 4247cbe0ff3SThierry Escande * is polling in target mode. 4257cbe0ff3SThierry Escande * If the device starts in dual mode polling, it switches between 4267cbe0ff3SThierry Escande * initiator and target at every round. 4277cbe0ff3SThierry Escande * Because the wq is ordered and only 1 work item is executed at a time, 4287cbe0ff3SThierry Escande * we'll always have one device polling as initiator and the other as 4297cbe0ff3SThierry Escande * target at some point, even if both are started in dual mode. 4307cbe0ff3SThierry Escande */ 4317cbe0ff3SThierry Escande queue_delayed_work(wq, &dev->poll_work, msecs_to_jiffies(200)); 4327cbe0ff3SThierry Escande 4337cbe0ff3SThierry Escande unlock: 4347cbe0ff3SThierry Escande mutex_unlock(&peer->lock); 4357cbe0ff3SThierry Escande mutex_unlock(&dev->lock); 4367cbe0ff3SThierry Escande } 4377cbe0ff3SThierry Escande 4387cbe0ff3SThierry Escande static struct nfcsim *nfcsim_init_dev(void) 4397cbe0ff3SThierry Escande { 4407cbe0ff3SThierry Escande struct nfcsim *dev; 4417cbe0ff3SThierry Escande int rc = -ENOMEM; 4427cbe0ff3SThierry Escande 4437cbe0ff3SThierry Escande dev = kzalloc(sizeof(*dev), GFP_KERNEL); 4447cbe0ff3SThierry Escande if (dev == NULL) 4457cbe0ff3SThierry Escande return ERR_PTR(-ENOMEM); 4467cbe0ff3SThierry Escande 4477cbe0ff3SThierry Escande mutex_init(&dev->lock); 4487cbe0ff3SThierry Escande 4497cbe0ff3SThierry Escande INIT_DELAYED_WORK(&dev->recv_work, nfcsim_wq_recv); 4507cbe0ff3SThierry Escande INIT_DELAYED_WORK(&dev->poll_work, nfcsim_wq_poll); 4517cbe0ff3SThierry Escande 4527cbe0ff3SThierry Escande dev->nfc_dev = nfc_allocate_device(&nfcsim_nfc_ops, 4537cbe0ff3SThierry Escande NFC_PROTO_NFC_DEP_MASK, 4547cbe0ff3SThierry Escande 0, 0); 4557cbe0ff3SThierry Escande if (!dev->nfc_dev) 4567cbe0ff3SThierry Escande goto error; 4577cbe0ff3SThierry Escande 4587cbe0ff3SThierry Escande nfc_set_drvdata(dev->nfc_dev, dev); 4597cbe0ff3SThierry Escande 4607cbe0ff3SThierry Escande rc = nfc_register_device(dev->nfc_dev); 4617cbe0ff3SThierry Escande if (rc) 4627cbe0ff3SThierry Escande goto free_nfc_dev; 4637cbe0ff3SThierry Escande 4647cbe0ff3SThierry Escande return dev; 4657cbe0ff3SThierry Escande 4667cbe0ff3SThierry Escande free_nfc_dev: 4677cbe0ff3SThierry Escande nfc_free_device(dev->nfc_dev); 4687cbe0ff3SThierry Escande 4697cbe0ff3SThierry Escande error: 4707cbe0ff3SThierry Escande kfree(dev); 4717cbe0ff3SThierry Escande 4727cbe0ff3SThierry Escande return ERR_PTR(rc); 4737cbe0ff3SThierry Escande } 4747cbe0ff3SThierry Escande 4757cbe0ff3SThierry Escande static void nfcsim_free_device(struct nfcsim *dev) 4767cbe0ff3SThierry Escande { 4777cbe0ff3SThierry Escande nfc_unregister_device(dev->nfc_dev); 4787cbe0ff3SThierry Escande 4797cbe0ff3SThierry Escande nfc_free_device(dev->nfc_dev); 4807cbe0ff3SThierry Escande 4817cbe0ff3SThierry Escande kfree(dev); 4827cbe0ff3SThierry Escande } 4837cbe0ff3SThierry Escande 484*40dac370SThierry Escande static int __init nfcsim_init(void) 4857cbe0ff3SThierry Escande { 4867cbe0ff3SThierry Escande int rc; 4877cbe0ff3SThierry Escande 4887cbe0ff3SThierry Escande /* We need an ordered wq to ensure that poll_work items are executed 4897cbe0ff3SThierry Escande * one at a time. 4907cbe0ff3SThierry Escande */ 4917cbe0ff3SThierry Escande wq = alloc_ordered_workqueue("nfcsim", 0); 4927cbe0ff3SThierry Escande if (!wq) { 4937cbe0ff3SThierry Escande rc = -ENOMEM; 4947cbe0ff3SThierry Escande goto exit; 4957cbe0ff3SThierry Escande } 4967cbe0ff3SThierry Escande 4977cbe0ff3SThierry Escande dev0 = nfcsim_init_dev(); 4987cbe0ff3SThierry Escande if (IS_ERR(dev0)) { 4997cbe0ff3SThierry Escande rc = PTR_ERR(dev0); 5007cbe0ff3SThierry Escande goto exit; 5017cbe0ff3SThierry Escande } 5027cbe0ff3SThierry Escande 5037cbe0ff3SThierry Escande dev1 = nfcsim_init_dev(); 5047cbe0ff3SThierry Escande if (IS_ERR(dev1)) { 5057cbe0ff3SThierry Escande kfree(dev0); 5067cbe0ff3SThierry Escande 5077cbe0ff3SThierry Escande rc = PTR_ERR(dev1); 5087cbe0ff3SThierry Escande goto exit; 5097cbe0ff3SThierry Escande } 5107cbe0ff3SThierry Escande 5117cbe0ff3SThierry Escande dev0->peer_dev = dev1; 5127cbe0ff3SThierry Escande dev1->peer_dev = dev0; 5137cbe0ff3SThierry Escande 5147cbe0ff3SThierry Escande pr_debug("NFCsim " NFCSIM_VERSION " initialized\n"); 5157cbe0ff3SThierry Escande 5167cbe0ff3SThierry Escande rc = 0; 5177cbe0ff3SThierry Escande exit: 5187cbe0ff3SThierry Escande if (rc) 5197cbe0ff3SThierry Escande pr_err("Failed to initialize nfcsim driver (%d)\n", 5207cbe0ff3SThierry Escande rc); 5217cbe0ff3SThierry Escande 5227cbe0ff3SThierry Escande return rc; 5237cbe0ff3SThierry Escande } 5247cbe0ff3SThierry Escande 525*40dac370SThierry Escande static void __exit nfcsim_exit(void) 5267cbe0ff3SThierry Escande { 5277cbe0ff3SThierry Escande nfcsim_cleanup_dev(dev0, 1); 5287cbe0ff3SThierry Escande nfcsim_cleanup_dev(dev1, 1); 5297cbe0ff3SThierry Escande 5307cbe0ff3SThierry Escande nfcsim_free_device(dev0); 5317cbe0ff3SThierry Escande nfcsim_free_device(dev1); 5327cbe0ff3SThierry Escande 5337cbe0ff3SThierry Escande destroy_workqueue(wq); 5347cbe0ff3SThierry Escande } 5357cbe0ff3SThierry Escande 5367cbe0ff3SThierry Escande module_init(nfcsim_init); 5377cbe0ff3SThierry Escande module_exit(nfcsim_exit); 5387cbe0ff3SThierry Escande 5397cbe0ff3SThierry Escande MODULE_DESCRIPTION("NFCSim driver ver " NFCSIM_VERSION); 5407cbe0ff3SThierry Escande MODULE_VERSION(NFCSIM_VERSION); 5417cbe0ff3SThierry Escande MODULE_LICENSE("GPL"); 542