diff --git a/chardev/chardev.c b/chardev/chardev.c index d0c74f8..e2c0fdc 100644 --- a/chardev/chardev.c +++ b/chardev/chardev.c @@ -1,9 +1,18 @@ #include "linux/fs.h" #include "linux/types.h" +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include +#include /* * Last compiled with Linux 6.14.5-300.fc42.x86_64 @@ -15,98 +24,109 @@ MODULE_VERSION("0.0.1"); MODULE_AUTHOR("Imbus"); MODULE_LICENSE("GPL"); +#define DEVICE_NAME "hello_cdev" + // Since were dynamically assigned a major device number, we will store it here -static int major; -static char text[64]; +static int major; +static char text[64]; +static struct class *cls; // Regular forward decls static ssize_t my_read(struct file *f, char __user *u, size_t l, loff_t *o); static ssize_t my_write(struct file *, const char __user *, size_t, loff_t *); -static int my_open(struct inode *, struct file *); -static int my_release(struct inode *, struct file *); +static int my_open(struct inode *, struct file *); +static int my_release(struct inode *, struct file *); // See: https://elixir.bootlin.com/linux/v6.14.5/source/include/linux/fs.h#L2131 static struct file_operations fops = { - .read = my_read, .write = my_write, .open = my_open, .release = my_release}; + .read = my_read, + .write = my_write, + .open = my_open, + .release = my_release, +}; -static ssize_t my_write(struct file *filp, const char __user *user_buf, - size_t len, loff_t *off) { - printk(KERN_INFO "hello_cdev - Write is called by %s...\n", current->comm); +static ssize_t my_write(struct file *filp, const char __user *user_buf, size_t len, loff_t *off) { + pr_info("hello_cdev - Write is called by %s...\n", current->comm); - int not_copied, delta, - to_copy = (len + *off) < sizeof(text) ? len : (sizeof(text) - *off); + int not_copied, delta, to_copy = (len + *off) < sizeof(text) ? len : (sizeof(text) - *off); - if (*off >= sizeof(text)) - return 0; + if (*off >= sizeof(text)) + return 0; - not_copied = copy_from_user(text, user_buf, to_copy); - delta = to_copy - not_copied; + not_copied = copy_from_user(text, user_buf, to_copy); + delta = to_copy - not_copied; - if (not_copied) - pr_warn("hello_cdev - Could only copy %d bytes\n", delta); + if (not_copied) + pr_warn("hello_cdev - Could only copy %d bytes\n", delta); - *off = delta; + *off = delta; - return delta; + return delta; } -static ssize_t my_read(struct file *filp, char __user *user_buf, size_t len, - loff_t *off) { - printk(KERN_INFO "hello_cdev - Read is called\n"); +static ssize_t my_read(struct file *filp, char __user *user_buf, size_t len, loff_t *off) { + pr_info("hello_cdev - Read is called\n"); - int not_copied, delta, - to_copy = (len + *off) < sizeof(text) ? len : (sizeof(text) - *off); + int not_copied, delta, to_copy = (len + *off) < sizeof(text) ? len : (sizeof(text) - *off); - if (*off >= sizeof(text)) - return 0; + if (*off >= sizeof(text)) + return 0; - not_copied = copy_to_user(user_buf, text, to_copy); - delta = to_copy - not_copied; + not_copied = copy_to_user(user_buf, text, to_copy); + delta = to_copy - not_copied; - if (not_copied) - pr_warn("hello_cdev - Could only copy %d bytes\n", delta); + if (not_copied) + pr_warn("hello_cdev - Could only copy %d bytes\n", delta); - *off = delta; + *off = delta; - return delta; + return delta; } static int my_open(struct inode *inode, struct file *filp) { - pr_info("hello-cdev - Major %d, Minor %d\n", imajor(inode), iminor(inode)); + pr_info("hello-cdev - Major %d, Minor %d\n", imajor(inode), iminor(inode)); + pr_info("hello-cdev - filp->f_pos: %lld\n", filp->f_pos); + pr_info("hello-cdev - filp->f_mode: 0x%x\n", filp->f_mode); + pr_info("hello-cdev - filp->f_flags: 0x%x\n", filp->f_flags); - pr_info("hello-cdev - filp->f_pos: %lld\n", filp->f_pos); - pr_info("hello-cdev - filp->f_mode: 0x%x\n", filp->f_mode); - pr_info("hello-cdev - filp->f_flags: 0x%x\n", filp->f_flags); - - return 0; + return 0; } static int my_release(struct inode *inode, struct file *filp) { - pr_info("hello-cdev - Closed \n"); - return 0; + pr_info("hello-cdev - Closed \n"); + return 0; } /** * @brief Called on load */ static int __init demo_mod_init(void) { - major = register_chrdev(0, "hello_cdev", &fops); + major = register_chrdev(0, DEVICE_NAME, &fops); - if (major < 0) { - printk(KERN_INFO "hello_cdev - Error registering chrdev\n"); - return major; - } + if (major < 0) { + pr_info("hello_cdev - Error registering chrdev\n"); + return major; + } - printk(KERN_INFO "hello_cdev - Major nbr %d loaded successfully...", major); - return 0; + pr_info("I was assigned major number %d.\n", major); + + cls = class_create(DEVICE_NAME); + device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); + + pr_info("Device created on /dev/%s\n", DEVICE_NAME); + + pr_info("hello_cdev - Major nbr %d loaded successfully...", major); + return 0; } /** * @brief Called on unload */ static void __exit demo_mod_exit(void) { - unregister_chrdev(major, "hello_cdev"); - printk(KERN_INFO "hello_cdev - unloaded successfully..."); + device_destroy(cls, MKDEV(major, 0)); + class_destroy(cls); + unregister_chrdev(major, DEVICE_NAME); + pr_info("hello_cdev - unloaded successfully..."); } module_init(demo_mod_init);