/** * @file demo_misc.c * @author your name (you@domain.com) * @brief * @version 0.1 * @date 2019-10-15 * * @copyright Copyright (c) 2019 * */ #include #include #include #include #include MODULE_AUTHOR("Rick Chan"); MODULE_LICENSE("GPL"); #define IOCTL_IOC_SIZE 8 #define IOCTL_IOC _IOC(_IOC_READ|_IOC_WRITE, 0, 0, IOCTL_IOC_SIZE) #define IOCTL_IO _IO(0, 1) #define IOCTL_IOR _IOR(0, 2, uint16_t) #define IOCTL_IOW _IOW(0, 3, int32_t) #define IOCTL_IOWR _IOWR(0, 4, uint32_t) static int demo_open(struct inode *inode, struct file* filp) { return 0; } static int demo_release(struct inode *inode, struct file* filp) { return 0; } static loff_t demo_llseek(struct file *filp, loff_t offset, int origin) { return filp->f_pos; } static ssize_t demo_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset) { const char __user *p = buffer; return p-buffer; } static ssize_t demo_write(struct file *filp, const char __user *buffer, size_t count, loff_t *offset) { const char __user *p = buffer; return p-buffer; } static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case IOCTL_IOC: { uint8_t tmp[IOCTL_IOC_SIZE]; copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd)); copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd)); } break; case IOCTL_IO: break; case IOCTL_IOR: { uint16_t tmp = 0x55AA; copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd)); } break; case IOCTL_IOW: { int32_t tmp = 0; copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd)); } break; case IOCTL_IOWR: { uint32_t tmp = 0; copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd)); copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd)); } break; default: return -ENOIOCTLCMD; } return 0; } static int demo_mmap(struct file* filp, struct vm_area_struct* vma) { return 0; } static struct file_operations demo_fops = { .owner = THIS_MODULE, .open = demo_open, .release = demo_release, .llseek = demo_llseek, .read = demo_read, .write = demo_write, .unlocked_ioctl = demo_ioctl, .mmap = demo_mmap }; static struct miscdevice demo_dev = { .minor = MISC_DYNAMIC_MINOR, // Dynamically allocate minor. .name = "demo_misc", .fops = &demo_fops, }; static int __init demo_init(void) { misc_register(&demo_dev); return 0; } static void __exit demo_exit(void) { misc_deregister(&demo_dev); } module_init(demo_init); module_exit(demo_exit);