// 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;
	bool running;
};

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

	vdev->running = true;
	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;
	vdev->running = false;
	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 || !vdev->running) {
		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,
};

module_misc_device(miscdev);

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