From dec43eba2a1dfb51d963631ae373ab9577ae38da Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sun, 17 May 2009 23:54:01 +0000 Subject: initial checkin --- Makefile | 7 ++++ iir.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 Makefile create mode 100644 iir.c 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 +#include +#include +#include +#include /* 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; +} -- cgit v1.2.3