diff options
Diffstat (limited to 'handlers')
-rw-r--r-- | handlers/Makefile | 8 | ||||
-rw-r--r-- | handlers/chardev.c | 105 | ||||
-rw-r--r-- | handlers/chardev.h | 4 | ||||
-rw-r--r-- | handlers/procfs1.c | 50 |
4 files changed, 167 insertions, 0 deletions
diff --git a/handlers/Makefile b/handlers/Makefile new file mode 100644 index 0000000..10043eb --- /dev/null +++ b/handlers/Makefile @@ -0,0 +1,8 @@ +obj-m += chardev.o +obj-m += procfs1.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/handlers/chardev.c b/handlers/chardev.c new file mode 100644 index 0000000..3594bce --- /dev/null +++ b/handlers/chardev.c @@ -0,0 +1,105 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <asm/uaccess.h> + +#include "chardev.h" + +#define SUCCESS 0 +#define DEVICE_NAME "chardev" +#define BUF_LEN 80 + +static int Major; +static int opened = 0; +static char msg[BUF_LEN]; +static char* msg_ptr; + +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(msg, "Come on, write something here :D\n"); + + msg_ptr = msg; + 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* buffer, size_t len, loff_t* off) +{ + int bytes = 0; + + if (*msg_ptr == 0) + return 0; + + while (len-- && *msg_ptr) { + put_user(*msg_ptr++, buffer++); + 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(msg[bytes], buff++); + bytes++; + } + msg[bytes] = '\0'; + + msg_ptr = msg; + return bytes; +} diff --git a/handlers/chardev.h b/handlers/chardev.h new file mode 100644 index 0000000..23b010a --- /dev/null +++ b/handlers/chardev.h @@ -0,0 +1,4 @@ +static int device_open(struct inode*, struct file*); +static int device_release(struct inode*, struct file*); +static ssize_t device_read(struct file*, char*, size_t, loff_t*); +static ssize_t device_write(struct file*, const char*, size_t, loff_t*); diff --git a/handlers/procfs1.c b/handlers/procfs1.c new file mode 100644 index 0000000..9d96319 --- /dev/null +++ b/handlers/procfs1.c @@ -0,0 +1,50 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/proc_fs.h> + +#define procfs_name "helloworld" + +struct proc_dir_entry* Our_Proc_File; +struct proc_dir_entry proc_root; + +int procfile_read(char* buf, char** buf_loc, off_t off, int buf_len, int* eof, void* data) +{ + int ret; + + printk(KERN_INFO "procfile_read (/proc/%s) called\n", procfs_name); + + if (off > 0) + ret = 0; + else + ret = sprintf(buf, "HelloWorld!\n"); + + return ret; +} + +int init_module(void) +{ + Our_Proc_File = create_proc_entry(procfs_name, 0644, NULL); + + if (Our_Proc_File == NULL) { + remove_proc_entry(procfs_name, NULL); + //remove_proc_entry(procfs_name, &proc_root); + printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", procfs_name); + return -ENOMEM; + } + + Our_Proc_File->read_proc = procfile_read; + Our_Proc_File->mode = S_IFREG | S_IRUGO; + Our_Proc_File->uid = 0; + Our_Proc_File->gid = 0; + Our_Proc_File->size = 37; + + printk(KERN_INFO "/proc/%s created\n", procfs_name); + return 0; +} + +void cleanup_module(void) +{ + remove_proc_entry(procfs_name, NULL); + //remove_proc_entry(procfs_name, &proc_root); + printk(KERN_INFO "/proc/%s removed\n", procfs_name); +} |