summaryrefslogtreecommitdiff
path: root/handlers/chardev.c
diff options
context:
space:
mode:
Diffstat (limited to 'handlers/chardev.c')
-rw-r--r--handlers/chardev.c105
1 files changed, 105 insertions, 0 deletions
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;
+}