// SPDX-License-Identifier: GPL-2.0 #include #include #include static int major; static char text[64]; static ssize_t my_read (struct file *filp, char __user *user_buf, size_t length, loff_t *offset) { /* if len + off is less than text size then size is = len, else it is size - offset */ int not_copied, delta, to_copy = (length + *offset) < sizeof(text) ? length : (sizeof(text) - *offset); pr_info("hello_cdev - Read is called, we want to read %u bytes, but actually only coping %d bytes. The offset is %lld\n", length, to_copy, *offset); if(*offset >= sizeof(text)) return 0; not_copied = copy_to_user(user_buf, &text[*offset], to_copy); delta = to_copy - not_copied; if(not_copied) pr_warn("hello_cdev - Could only copy %d bytes\n", delta); *offset += delta; return delta; } static ssize_t my_write (struct file *filp, const char __user *user_buf, size_t length, loff_t *offset) { /* if len + off is less than text size then size is = len, else it is size - offset */ int not_copied, delta, to_copy = (length + *offset) < sizeof(text) ? length : (sizeof(text) - *offset); pr_info("hello_cdev - Write is called, we want to write %u bytes, but actually only coping %d bytes. The offset is %lld\n", length, to_copy, *offset); if(*offset >= sizeof(text)) return 0; not_copied = copy_from_user(&text[*offset], user_buf, to_copy); delta = to_copy - not_copied; if(not_copied) pr_warn("hello_cdev - Could only copy %d bytes\n", delta); *offset += delta; return delta; } static struct file_operations fops = { .read = my_read, .write = my_write }; /** * @brief This function is called when the module is loaded into the kernel */ static int __init my_init(void) { /** * First argument 0 auto allocates major device number * returns device number * Enter a number eg 64 to allocate all minor num 0 - 255 * 0 returned if successfull */ major = register_chrdev(0, "hello_cdev", &fops); if (major < 0) { pr_err("hello_cdev - Error registering chrdev\n"); return major; } pr_info("hello_cdev - Major device number: %d\n", major); return 0; } /** * @brief This function is called when the module is removed from the kernel */ static void __exit my_exit(void) { pr_info("Goodbye, Kernel\n"); unregister_chrdev(major, "hello_cdev"); } module_init(my_init); module_exit(my_exit); /* Meta Information */ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("David D'Ulisse"); MODULE_DESCRIPTION("A simple character device driver");