#include #include #include #include #include #include "chardev.h" #define SUCCESS 0 #define DEVICE_NAME "chardev" #define BUF_LEN 80 static int Major; static int opened = 0; static char chardev_buffer[BUF_LEN]; static char* msg_ptr; void dumb(void) { printk(KERN_INFO "DUMB EXECUTED\n"); } EXPORT_SYMBOL(dumb); static struct file_operations fops = { .read = device_read, .write = device_write, .open = device_open, .release = device_release }; int init_module(void) { Major = register_chrdev(0, DEVICE_NAME, &fops); if (Major < 0) { printk(KERN_ALERT "Registering char device failed with %d\n", Major); return Major; } printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major); printk(KERN_INFO "the driver, create a dev file with\n"); printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major); printk(KERN_INFO "Try to cat and echo to the device file.\n"); printk(KERN_INFO "Remove the device file and module when done.\n"); return SUCCESS; } void cleanup_module(void) { unregister_chrdev(Major, DEVICE_NAME); } static int device_open(struct inode* inode, struct file* filp) { static int counter = 0; if (opened) return -EBUSY; opened++; if (counter++ == 0) sprintf(chardev_buffer, "Come on, write something here :D\n"); msg_ptr = chardev_buffer; try_module_get(THIS_MODULE); return SUCCESS; } static int device_release(struct inode* inode, struct file* filp) { opened--; module_put(THIS_MODULE); return 0; } static ssize_t device_read(struct file* filp, char* buff, size_t len, loff_t* off) { int bytes = 0; char strpid[14]; snprintf(strpid, 14, "PID: %d", (current->pid)); if (*msg_ptr == 0) return 0; while (len-- && *msg_ptr) { put_user(*msg_ptr++, buff++); bytes++; } copy_to_user(buff, strpid, 14); bytes += 14; buff += 14; put_user('\n', buff++); bytes++; return bytes; } static ssize_t device_write(struct file* filp, const char* buff, size_t len, loff_t* off) { int bytes = 0; if (len > BUF_LEN) { printk(KERN_ALERT "Error: dude you tried to overflow my buffer!\n"); return -ENOBUFS; } while (len--) { get_user(chardev_buffer[bytes], buff++); bytes++; } chardev_buffer[bytes] = '\0'; msg_ptr = chardev_buffer; return bytes; }