summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2009-05-17 23:54:01 (GMT)
committerChristian Pointner <equinox@spreadspace.org>2009-05-17 23:54:01 (GMT)
commitdec43eba2a1dfb51d963631ae373ab9577ae38da (patch)
tree17e4388951e145da0076c0ed286f2520dd136805
initial checkin
-rw-r--r--Makefile7
-rw-r--r--iir.c141
2 files changed, 148 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..64c8958
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+obj-m += iir.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 \ No newline at end of file
diff --git a/iir.c b/iir.c
new file mode 100644
index 0000000..5ddea79
--- /dev/null
+++ b/iir.c
@@ -0,0 +1,141 @@
+/*
+ * iir.c: Creates a read-only char device that always gives you a random number
+ * iir stands for: infinite improbable randomness
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <asm/uaccess.h> /* for put_user */
+
+/*
+ * Prototypes - this would normally go in a .h file
+ */
+int init_module(void);
+void cleanup_module(void);
+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 *);
+
+#define SUCCESS 0
+#define DEVICE_NAME "iir" /* Dev name as it appears in /proc/devices */
+
+/*
+ * Global variables are declared as static, so are global within the file.
+ */
+
+static int Major; /* Major number assigned to our device driver */
+
+static struct file_operations fops = {
+ .read = device_read,
+ .write = device_write,
+ .open = device_open,
+ .release = device_release
+};
+
+/*
+ * This function is called when the module is loaded
+ */
+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 "infinite improbable randomness loaded (major number %d)\n", Major);
+
+ return SUCCESS;
+}
+
+/*
+ * This function is called when the module is unloaded
+ */
+void cleanup_module(void)
+{
+ /*
+ * Unregister the device
+ */
+ unregister_chrdev(Major, DEVICE_NAME);
+
+ printk(KERN_INFO "infinite improbable randomness unloaded\n");
+}
+
+/*
+ * Methods
+ */
+
+/*
+ * Called when a process tries to open the device file, like
+ * "cat /dev/mycharfile"
+ */
+static int device_open(struct inode *inode, struct file *file)
+{
+ try_module_get(THIS_MODULE);
+
+ return SUCCESS;
+}
+
+/*
+ * Called when a process closes the device file.
+ */
+static int device_release(struct inode *inode, struct file *file)
+{
+ /*
+ * Decrement the usage count, or else once you opened the file, you'll
+ * never get get rid of the module.
+ */
+ module_put(THIS_MODULE);
+
+ return 0;
+}
+
+/*
+ * Called when a process, which already opened the dev file, attempts to
+ * read from it.
+ */
+static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
+ char *buffer, /* buffer to fill with data */
+ size_t length, /* length of the buffer */
+ loff_t * offset)
+{
+ /*
+ * Actually put the data into the buffer
+ */
+ size_t read = 0;
+ while (length) {
+
+ /*
+ * The buffer is in the user data segment, not the kernel
+ * segment so "*" assignment won't work. We have to use
+ * put_user which copies data from the kernel data segment to
+ * the user data segment.
+ */
+ put_user('9', buffer++);
+
+ length--;
+ read++;
+ }
+
+ /*
+ * Most read functions return the number of bytes put into the buffer
+ */
+ return read;
+}
+
+/*
+ * Called when a process writes to dev file: echo "hi" > /dev/hello
+ */
+static ssize_t
+device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
+{
+ if(!strncmp(buff, "are you really that random?", len)) {
+ printk(KERN_INFO "That's the problem with randomness, you can never be sure.\n");
+ return len;
+ }
+ return -EINVAL;
+}