#include #include #include #include #include #include #include #include MODULE_DESCRIPTION("Character device driver"); MODULE_AUTHOR("so"); MODULE_LICENSE("GPL"); static int driver_open(struct inode *inode, struct file *file) { printk(KERN_ALERT "Open\n"); return 0; // return successfully } static int driver_release(struct inode *inode, struct file *file) { printk(KERN_ALERT "Release\n"); return 0; // return successfully } static ssize_t driver_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset) { printk(KERN_ALERT "Read %d chars\n", size); return 0; // tell the caller that there aren't any character available for reading // If we return a number > 0, this function will be called forever by the 'cat' command. // It won't stop if we don't tell it that we don't have any more data. } static ssize_t driver_write(struct file *file, const char __user *user_buffer, size_t size, loff_t *offset) { // we need to copy the data to a kernel buffer char* buf = kmalloc(size + 1, GFP_KERNEL); buf[size] = 0; copy_from_user(buf, user_buffer, size); // copy `size` bytes from user_buffer to buf printk(KERN_ALERT "Write %d chars: %s\n", size, buf); kfree(buf); // free our kernel buffer return size; // tell the caller that all characters have been successfully written // If we return a number < size, this function will be called forever by the 'echo' command. // It won't stop until all the data has been succesfully written. } static struct file_operations driver_fops = { .owner = THIS_MODULE, .open = driver_open, .release = driver_release, .read = driver_read, .write = driver_write, }; static struct cdev cdev; static int so2_cdev_init(void) { int err; printk(KERN_ALERT "Entering driver module\n"); // this module acquires a device code. This code is composed of two numbers: a major (42) and a minor (0) err = register_chrdev_region(MKDEV(42, 0), 1, "driver"); if (err != 0) { printk(KERN_ALERT "register_chrdev_region error: %d\n", err); return err; } // assign the operations above to our device cdev_init(&cdev, &driver_fops); // assign the device code to our device, and tell the kernel that our device is ready to receive calls err = cdev_add(&cdev, MKDEV(42, 0), 1); if (err != 0) { printk(KERN_ALERT "cdev_add error: %d\n", err); return err; } return 0; } static void so2_cdev_exit(void) { printk(KERN_ALERT "Exiting driver module\n"); // tell the kernel that our device doesn't want to receive any more calls cdev_del(&cdev); // release the unregister_chrdev_region(MKDEV(42, 0), 1); } module_init(so2_cdev_init); module_exit(so2_cdev_exit);