summaryrefslogtreecommitdiff
path: root/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'handlers')
-rw-r--r--handlers/Makefile8
-rw-r--r--handlers/chardev.c105
-rw-r--r--handlers/chardev.h4
-rw-r--r--handlers/procfs1.c50
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);
+}