VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   55 Tags
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   1) // SPDX-License-Identifier: GPL-2.0-or-later
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   2) /*
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   3)  * Virtual NCI device simulation driver
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   4)  *
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   5)  * Copyright (C) 2020 Samsung Electrnoics
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   6)  * Bongsu Jeon <bongsu.jeon@samsung.com>
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   7)  */
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   8) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900   9) #include <linux/kernel.h>
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  10) #include <linux/module.h>
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  11) #include <linux/miscdevice.h>
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  12) #include <linux/mutex.h>
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  13) #include <net/nfc/nci_core.h>
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  14) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  15) enum virtual_ncidev_mode {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  16) 	virtual_ncidev_enabled,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  17) 	virtual_ncidev_disabled,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  18) 	virtual_ncidev_disabling,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  19) };
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  20) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  21) #define IOCTL_GET_NCIDEV_IDX    0
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  22) #define VIRTUAL_NFC_PROTOCOLS	(NFC_PROTO_JEWEL_MASK | \
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  23) 				 NFC_PROTO_MIFARE_MASK | \
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  24) 				 NFC_PROTO_FELICA_MASK | \
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  25) 				 NFC_PROTO_ISO14443_MASK | \
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  26) 				 NFC_PROTO_ISO14443_B_MASK | \
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  27) 				 NFC_PROTO_ISO15693_MASK)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  28) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  29) static enum virtual_ncidev_mode state;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  30) static struct miscdevice miscdev;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  31) static struct sk_buff *send_buff;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  32) static struct nci_dev *ndev;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  33) static DEFINE_MUTEX(nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  34) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  35) static int virtual_nci_open(struct nci_dev *ndev)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  36) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  37) 	return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  38) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  39) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  40) static int virtual_nci_close(struct nci_dev *ndev)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  41) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  42) 	mutex_lock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  43) 	kfree_skb(send_buff);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  44) 	send_buff = NULL;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  45) 	mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  46) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  47) 	return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  48) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  49) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  50) static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  51) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  52) 	mutex_lock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  53) 	if (state != virtual_ncidev_enabled) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  54) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  55) 		return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  56) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  57) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  58) 	if (send_buff) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  59) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  60) 		return -1;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  61) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  62) 	send_buff = skb_copy(skb, GFP_KERNEL);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  63) 	mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  64) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  65) 	return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  66) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  67) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  68) static struct nci_ops virtual_nci_ops = {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  69) 	.open = virtual_nci_open,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  70) 	.close = virtual_nci_close,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  71) 	.send = virtual_nci_send
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  72) };
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  73) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  74) static ssize_t virtual_ncidev_read(struct file *file, char __user *buf,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  75) 				   size_t count, loff_t *ppos)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  76) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  77) 	size_t actual_len;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  78) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  79) 	mutex_lock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  80) 	if (!send_buff) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  81) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  82) 		return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  83) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  84) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  85) 	actual_len = min_t(size_t, count, send_buff->len);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  86) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  87) 	if (copy_to_user(buf, send_buff->data, actual_len)) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  88) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  89) 		return -EFAULT;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  90) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  91) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  92) 	skb_pull(send_buff, actual_len);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  93) 	if (send_buff->len == 0) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  94) 		consume_skb(send_buff);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  95) 		send_buff = NULL;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  96) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  97) 	mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  98) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900  99) 	return actual_len;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 100) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 101) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 102) static ssize_t virtual_ncidev_write(struct file *file,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 103) 				    const char __user *buf,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 104) 				    size_t count, loff_t *ppos)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 105) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 106) 	struct sk_buff *skb;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 107) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 108) 	skb = alloc_skb(count, GFP_KERNEL);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 109) 	if (!skb)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 110) 		return -ENOMEM;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 111) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 112) 	if (copy_from_user(skb_put(skb, count), buf, count)) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 113) 		kfree_skb(skb);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 114) 		return -EFAULT;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 115) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 116) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 117) 	nci_recv_frame(ndev, skb);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 118) 	return count;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 119) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 120) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 121) static int virtual_ncidev_open(struct inode *inode, struct file *file)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 122) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 123) 	int ret = 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 124) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 125) 	mutex_lock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 126) 	if (state != virtual_ncidev_disabled) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 127) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 128) 		return -EBUSY;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 129) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 130) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 131) 	ndev = nci_allocate_device(&virtual_nci_ops, VIRTUAL_NFC_PROTOCOLS,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 132) 				   0, 0);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 133) 	if (!ndev) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 134) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 135) 		return -ENOMEM;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 136) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 137) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 138) 	ret = nci_register_device(ndev);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 139) 	if (ret < 0) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 140) 		nci_free_device(ndev);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 141) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 142) 		return ret;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 143) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 144) 	state = virtual_ncidev_enabled;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 145) 	mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 146) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 147) 	return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 148) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 149) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 150) static int virtual_ncidev_close(struct inode *inode, struct file *file)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 151) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 152) 	mutex_lock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 153) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 154) 	if (state == virtual_ncidev_enabled) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 155) 		state = virtual_ncidev_disabling;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 156) 		mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 157) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 158) 		nci_unregister_device(ndev);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 159) 		nci_free_device(ndev);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 160) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 161) 		mutex_lock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 162) 	}
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 163) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 164) 	state = virtual_ncidev_disabled;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 165) 	mutex_unlock(&nci_mutex);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 166) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 167) 	return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 168) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 169) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 170) static long virtual_ncidev_ioctl(struct file *flip, unsigned int cmd,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 171) 				 unsigned long arg)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 172) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 173) 	struct nfc_dev *nfc_dev = ndev->nfc_dev;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 174) 	void __user *p = (void __user *)arg;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 175) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 176) 	if (cmd != IOCTL_GET_NCIDEV_IDX)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 177) 		return -ENOTTY;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 178) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 179) 	if (copy_to_user(p, &nfc_dev->idx, sizeof(nfc_dev->idx)))
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 180) 		return -EFAULT;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 181) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 182) 	return 0;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 183) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 184) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 185) static const struct file_operations virtual_ncidev_fops = {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 186) 	.owner = THIS_MODULE,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 187) 	.read = virtual_ncidev_read,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 188) 	.write = virtual_ncidev_write,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 189) 	.open = virtual_ncidev_open,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 190) 	.release = virtual_ncidev_close,
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 191) 	.unlocked_ioctl = virtual_ncidev_ioctl
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 192) };
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 193) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 194) static int __init virtual_ncidev_init(void)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 195) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 196) 	state = virtual_ncidev_disabled;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 197) 	miscdev.minor = MISC_DYNAMIC_MINOR;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 198) 	miscdev.name = "virtual_nci";
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 199) 	miscdev.fops = &virtual_ncidev_fops;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 200) 	miscdev.mode = S_IALLUGO;
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 201) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 202) 	return misc_register(&miscdev);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 203) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 204) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 205) static void __exit virtual_ncidev_exit(void)
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 206) {
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 207) 	misc_deregister(&miscdev);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 208) }
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 209) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 210) module_init(virtual_ncidev_init);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 211) module_exit(virtual_ncidev_exit);
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 212) 
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 213) MODULE_LICENSE("GPL");
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 214) MODULE_DESCRIPTION("Virtual NCI device simulation driver");
e624e6c3e777f (Bongsu Jeon 2021-01-27 22:08:28 +0900 215) MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");