0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/miscdevice.h>
0012 #include <linux/mutex.h>
0013 #include <linux/wait.h>
0014 #include <net/nfc/nci_core.h>
0015
0016 enum virtual_ncidev_mode {
0017 virtual_ncidev_enabled,
0018 virtual_ncidev_disabled,
0019 virtual_ncidev_disabling,
0020 };
0021
0022 #define IOCTL_GET_NCIDEV_IDX 0
0023 #define VIRTUAL_NFC_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
0024 NFC_PROTO_MIFARE_MASK | \
0025 NFC_PROTO_FELICA_MASK | \
0026 NFC_PROTO_ISO14443_MASK | \
0027 NFC_PROTO_ISO14443_B_MASK | \
0028 NFC_PROTO_ISO15693_MASK)
0029
0030 static enum virtual_ncidev_mode state;
0031 static DECLARE_WAIT_QUEUE_HEAD(wq);
0032 static struct miscdevice miscdev;
0033 static struct sk_buff *send_buff;
0034 static struct nci_dev *ndev;
0035 static DEFINE_MUTEX(nci_mutex);
0036
0037 static int virtual_nci_open(struct nci_dev *ndev)
0038 {
0039 return 0;
0040 }
0041
0042 static int virtual_nci_close(struct nci_dev *ndev)
0043 {
0044 mutex_lock(&nci_mutex);
0045 kfree_skb(send_buff);
0046 send_buff = NULL;
0047 mutex_unlock(&nci_mutex);
0048
0049 return 0;
0050 }
0051
0052 static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
0053 {
0054 mutex_lock(&nci_mutex);
0055 if (state != virtual_ncidev_enabled) {
0056 mutex_unlock(&nci_mutex);
0057 return 0;
0058 }
0059
0060 if (send_buff) {
0061 mutex_unlock(&nci_mutex);
0062 return -1;
0063 }
0064 send_buff = skb_copy(skb, GFP_KERNEL);
0065 mutex_unlock(&nci_mutex);
0066 wake_up_interruptible(&wq);
0067
0068 return 0;
0069 }
0070
0071 static const struct nci_ops virtual_nci_ops = {
0072 .open = virtual_nci_open,
0073 .close = virtual_nci_close,
0074 .send = virtual_nci_send
0075 };
0076
0077 static ssize_t virtual_ncidev_read(struct file *file, char __user *buf,
0078 size_t count, loff_t *ppos)
0079 {
0080 size_t actual_len;
0081
0082 mutex_lock(&nci_mutex);
0083 while (!send_buff) {
0084 mutex_unlock(&nci_mutex);
0085 if (wait_event_interruptible(wq, send_buff))
0086 return -EFAULT;
0087 mutex_lock(&nci_mutex);
0088 }
0089
0090 actual_len = min_t(size_t, count, send_buff->len);
0091
0092 if (copy_to_user(buf, send_buff->data, actual_len)) {
0093 mutex_unlock(&nci_mutex);
0094 return -EFAULT;
0095 }
0096
0097 skb_pull(send_buff, actual_len);
0098 if (send_buff->len == 0) {
0099 consume_skb(send_buff);
0100 send_buff = NULL;
0101 }
0102 mutex_unlock(&nci_mutex);
0103
0104 return actual_len;
0105 }
0106
0107 static ssize_t virtual_ncidev_write(struct file *file,
0108 const char __user *buf,
0109 size_t count, loff_t *ppos)
0110 {
0111 struct sk_buff *skb;
0112
0113 skb = alloc_skb(count, GFP_KERNEL);
0114 if (!skb)
0115 return -ENOMEM;
0116
0117 if (copy_from_user(skb_put(skb, count), buf, count)) {
0118 kfree_skb(skb);
0119 return -EFAULT;
0120 }
0121
0122 nci_recv_frame(ndev, skb);
0123 return count;
0124 }
0125
0126 static int virtual_ncidev_open(struct inode *inode, struct file *file)
0127 {
0128 int ret = 0;
0129
0130 mutex_lock(&nci_mutex);
0131 if (state != virtual_ncidev_disabled) {
0132 mutex_unlock(&nci_mutex);
0133 return -EBUSY;
0134 }
0135
0136 ndev = nci_allocate_device(&virtual_nci_ops, VIRTUAL_NFC_PROTOCOLS,
0137 0, 0);
0138 if (!ndev) {
0139 mutex_unlock(&nci_mutex);
0140 return -ENOMEM;
0141 }
0142
0143 ret = nci_register_device(ndev);
0144 if (ret < 0) {
0145 nci_free_device(ndev);
0146 mutex_unlock(&nci_mutex);
0147 return ret;
0148 }
0149 state = virtual_ncidev_enabled;
0150 mutex_unlock(&nci_mutex);
0151
0152 return 0;
0153 }
0154
0155 static int virtual_ncidev_close(struct inode *inode, struct file *file)
0156 {
0157 mutex_lock(&nci_mutex);
0158
0159 if (state == virtual_ncidev_enabled) {
0160 state = virtual_ncidev_disabling;
0161 mutex_unlock(&nci_mutex);
0162
0163 nci_unregister_device(ndev);
0164 nci_free_device(ndev);
0165
0166 mutex_lock(&nci_mutex);
0167 }
0168
0169 state = virtual_ncidev_disabled;
0170 mutex_unlock(&nci_mutex);
0171
0172 return 0;
0173 }
0174
0175 static long virtual_ncidev_ioctl(struct file *flip, unsigned int cmd,
0176 unsigned long arg)
0177 {
0178 const struct nfc_dev *nfc_dev = ndev->nfc_dev;
0179 void __user *p = (void __user *)arg;
0180
0181 if (cmd != IOCTL_GET_NCIDEV_IDX)
0182 return -ENOTTY;
0183
0184 if (copy_to_user(p, &nfc_dev->idx, sizeof(nfc_dev->idx)))
0185 return -EFAULT;
0186
0187 return 0;
0188 }
0189
0190 static const struct file_operations virtual_ncidev_fops = {
0191 .owner = THIS_MODULE,
0192 .read = virtual_ncidev_read,
0193 .write = virtual_ncidev_write,
0194 .open = virtual_ncidev_open,
0195 .release = virtual_ncidev_close,
0196 .unlocked_ioctl = virtual_ncidev_ioctl
0197 };
0198
0199 static int __init virtual_ncidev_init(void)
0200 {
0201 state = virtual_ncidev_disabled;
0202 miscdev.minor = MISC_DYNAMIC_MINOR;
0203 miscdev.name = "virtual_nci";
0204 miscdev.fops = &virtual_ncidev_fops;
0205 miscdev.mode = 0600;
0206
0207 return misc_register(&miscdev);
0208 }
0209
0210 static void __exit virtual_ncidev_exit(void)
0211 {
0212 misc_deregister(&miscdev);
0213 }
0214
0215 module_init(virtual_ncidev_init);
0216 module_exit(virtual_ncidev_exit);
0217
0218 MODULE_LICENSE("GPL");
0219 MODULE_DESCRIPTION("Virtual NCI device simulation driver");
0220 MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");