// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Virtual NCI device simulation driver
 *
 * Copyright (C) 2020 Samsung Electrnoics
 * Bongsu Jeon <bongsu.jeon@samsung.com>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <net/nfc/nci_core.h>

#define IOCTL_GET_NCIDEV_IDX    0
#define VIRTUAL_NFC_PROTOCOLS	(NFC_PROTO_JEWEL_MASK | \
				 NFC_PROTO_MIFARE_MASK | \
				 NFC_PROTO_FELICA_MASK | \
				 NFC_PROTO_ISO14443_MASK | \
				 NFC_PROTO_ISO14443_B_MASK | \
				 NFC_PROTO_ISO15693_MASK)

struct virtual_nci_dev {
	struct nci_dev *ndev;
	struct mutex mtx;
	struct sk_buff *send_buff;
	struct wait_queue_head wq;
};

static int virtual_nci_open(struct nci_dev *ndev)
{
	return 0;
}

static int virtual_nci_close(struct nci_dev *ndev)
{
	struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);

	mutex_lock(&vdev->mtx);
	kfree_skb(vdev->send_buff);
	vdev->send_buff = NULL;
	mutex_unlock(&vdev->mtx);

	return 0;
}

static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
{
	struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);

	mutex_lock(&vdev->mtx);
	if (vdev->send_buff) {
		mutex_unlock(&vdev->mtx);
		kfree_skb(skb);
		return -1;
	}
	vdev->send_buff = skb_copy(skb, GFP_KERNEL);
	if (!vdev->send_buff) {
		mutex_unlock(&vdev->mtx);
		kfree_skb(skb);
		return -1;
	}
	mutex_unlock(&vdev->mtx);
	wake_up_interruptible(&vdev->wq);
	consume_skb(skb);

	return 0;
}

static const struct nci_ops virtual_nci_ops = {
	.open = virtual_nci_open,
	.close = virtual_nci_close,
	.send = virtual_nci_send
};

static ssize_t virtual_ncidev_read(struct file *file, char __user *buf,
				   size_t count, loff_t *ppos)
{
	struct virtual_nci_dev *vdev = file->private_data;
	size_t actual_len;

	mutex_lock(&vdev->mtx);
	while (!vdev->send_buff) {
		mutex_unlock(&vdev->mtx);
		if (wait_event_interruptible(vdev->wq, vdev->send_buff))
			return -EFAULT;
		mutex_lock(&vdev->mtx);
	}

	actual_len = min_t(size_t, count, vdev->send_buff->len);

	if (copy_to_user(buf, vdev->send_buff->data, actual_len)) {
		mutex_unlock(&vdev->mtx);
		return -EFAULT;
	}

	skb_pull(vdev->send_buff, actual_len);
	if (vdev->send_buff->len == 0) {
		consume_skb(vdev->send_buff);
		vdev->send_buff = NULL;
	}
	mutex_unlock(&vdev->mtx);

	return actual_len;
}

static ssize_t virtual_ncidev_write(struct file *file,
				    const char __user *buf,
				    size_t count, loff_t *ppos)
{
	struct virtual_nci_dev *vdev = file->private_data;
	struct sk_buff *skb;

	skb = alloc_skb(count, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	if (copy_from_user(skb_put(skb, count), buf, count)) {
		kfree_skb(skb);
		return -EFAULT;
	}

	nci_recv_frame(vdev->ndev, skb);
	return count;
}

static int virtual_ncidev_open(struct inode *inode, struct file *file)
{
	int ret = 0;
	struct virtual_nci_dev *vdev;

	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
	if (!vdev)
		return -ENOMEM;
	vdev->ndev = nci_allocate_device(&virtual_nci_ops,
		VIRTUAL_NFC_PROTOCOLS, 0, 0);
	if (!vdev->ndev) {
		kfree(vdev);
		return -ENOMEM;
	}

	mutex_init(&vdev->mtx);
	init_waitqueue_head(&vdev->wq);
	file->private_data = vdev;
	nci_set_drvdata(vdev->ndev, vdev);

	ret = nci_register_device(vdev->ndev);
	if (ret < 0) {
		nci_free_device(vdev->ndev);
		mutex_destroy(&vdev->mtx);
		kfree(vdev);
		return ret;
	}

	return 0;
}

static int virtual_ncidev_close(struct inode *inode, struct file *file)
{
	struct virtual_nci_dev *vdev = file->private_data;

	nci_unregister_device(vdev->ndev);
	nci_free_device(vdev->ndev);
	mutex_destroy(&vdev->mtx);
	kfree(vdev);

	return 0;
}

static long virtual_ncidev_ioctl(struct file *file, unsigned int cmd,
				 unsigned long arg)
{
	struct virtual_nci_dev *vdev = file->private_data;
	const struct nfc_dev *nfc_dev = vdev->ndev->nfc_dev;
	void __user *p = (void __user *)arg;

	if (cmd != IOCTL_GET_NCIDEV_IDX)
		return -ENOTTY;

	if (copy_to_user(p, &nfc_dev->idx, sizeof(nfc_dev->idx)))
		return -EFAULT;

	return 0;
}

static const struct file_operations virtual_ncidev_fops = {
	.owner = THIS_MODULE,
	.read = virtual_ncidev_read,
	.write = virtual_ncidev_write,
	.open = virtual_ncidev_open,
	.release = virtual_ncidev_close,
	.unlocked_ioctl = virtual_ncidev_ioctl
};

static struct miscdevice miscdev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "virtual_nci",
	.fops = &virtual_ncidev_fops,
	.mode = 0600,
};

static int __init virtual_ncidev_init(void)
{
	return misc_register(&miscdev);
}

static void __exit virtual_ncidev_exit(void)
{
	misc_deregister(&miscdev);
}

module_init(virtual_ncidev_init);
module_exit(virtual_ncidev_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Virtual NCI device simulation driver");
MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
