#include #include #include #include "fopdrv.h" #include "config.h" struct cdev *cdev; struct device *dev; struct class *class; dev_t node; struct file_operations fops = { .read = fop_read, .write = fop_write, .open = fop_open, .release = fop_release, }; static int mod_init(void) { int err; err = alloc_chrdev_region(&node, 0, 1, DRV_NAME); if (err < 0) { printk(KERN_ERR "alloc_chrdev_region error %d\n", err); goto return_err; } class = class_create(DRV_NAME); if (IS_ERR_OR_NULL(class)) { err = PTR_ERR(class); printk(KERN_ERR "class_create error %d\n", err); goto free_class; } cdev = cdev_alloc(); if (!cdev) { err = ENOMEM; goto free_cdev; } cdev->ops = &fops; cdev_init(cdev, &fops); err = cdev_add(cdev, node, 1); if (err < 0) { printk(KERN_ERR "cdev_add error %d\n", err); goto free_cdev; } dev = device_create(class, NULL, node, NULL, DRV_NAME); if (IS_ERR_OR_NULL(dev)) { err = PTR_ERR(dev); printk(KERN_ERR "device_create error %d\n", err); goto free_device; } printk("%s() -> 0 (%d:%d)\n", __PRETTY_FUNCTION__, MAJOR(node), MINOR(node)); return 0; free_device: device_destroy(class, node); free_cdev: cdev_del(cdev); free_class: class_destroy(class); return_err: printk("%s() -> %d\n", __PRETTY_FUNCTION__, err); return err; } static void mod_exit(void) { device_destroy(class, node); cdev_del(cdev); class_destroy(class); printk("%s()\n", __PRETTY_FUNCTION__); } module_init(mod_init); module_exit(mod_exit); MODULE_LICENSE("Dual MIT/GPL");