From 816d79f3662908f210e7d834d6d0c9fa32535e6c Mon Sep 17 00:00:00 2001 From: root Date: Thu, 26 Oct 2017 20:06:07 +0200 Subject: [PATCH] Initial commit --- Makefile | 14 ++++++ one.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100755 Makefile create mode 100755 one.c diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..b8094e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +obj-m := one.o + +CURRENT = $(shell uname -r) +KDIR = /lib/modules/$(CURRENT)/build +PWD = $(shell pwd) + + +default: + make -C $(KDIR) M=$(PWD) modules + + +clean: + make -C $(KDIR) M=$(PWD) clean + diff --git a/one.c b/one.c new file mode 100755 index 0000000..c4b7b74 --- /dev/null +++ b/one.c @@ -0,0 +1,141 @@ + +#include /* Needed by all modules */ +#include /* Needed for KERN_INFO */ +#include /* Needed for the macros */ +#include +#include /* for put_user */ + + +#define DEVICE_NAME "one" + + +static char outputchar = '1'; +/* +* module_param(foo, int, 0000) +* The first param is the parameters name +* The second param is it's data type +* The final argument is the permissions bits, +* for exposing parameters in sysfs (if non−zero). +* e.g. change outputchar to 'a' with "echo "97" > /sys/module/one/parameter/outputchar" +*/ +module_param(outputchar, byte, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); +MODULE_PARM_DESC(outputchar, "Character that will be output by the device file"); + +static int major; /* Major number assigned to our device driver */ +static int device_opened = 0; + +/* + * Prototypes − this would normally go in a .h file + */ +static int one_init(void); +static void one_exit(void); +static int one_open(struct inode *, struct file *); +static int one_release(struct inode *, struct file *); +static ssize_t one_read(struct file *, char *, size_t, loff_t *); +static ssize_t one_write(struct file *, const char *, size_t, loff_t *); + + +static struct file_operations fops = + { + .owner = THIS_MODULE, + .read = one_read, + .write = one_write, + .open = one_open, + .release = one_release + }; + +static int __init one_init(void) + { + printk(KERN_INFO "Hello World from module one\n"); + + major = register_chrdev(0, DEVICE_NAME, &fops); + if (major < 0) + { + printk(KERN_ALERT "Error in register_chrdev:%d\n", major); + return major; + } + + printk(KERN_INFO "I was assigned major number %d.\n", major); + printk(KERN_INFO "Execute \"mknod /dev/one c %d 0\" to create device file.\n", major); + return 0; + } + + +static void __exit one_exit(void) + { + // Unregister the device + unregister_chrdev(major, DEVICE_NAME); + + printk(KERN_INFO "Goodbye World from module one\n"); + } + +/* + * Called when a process tries to open the device file, like + * "cat /dev/mycharfile" + */ +static int one_open(struct inode *inode, struct file *file) + { + if (device_opened) + return -EBUSY; + device_opened++; + return 0; + } + +/* +* Called when a process closes the device file. +*/ +static int one_release(struct inode *inode, struct file *file) + { + device_opened--; /* We're now ready for our next caller */ + return 0; + } + +/* + * Called when a process, which already opened the dev file, attempts to read from it. + */ +static ssize_t one_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) +{ +/* +* Number of bytes actually written to the buffer +*/ +int bytes_read = 0; +// Copying data to the buffer +int i; +for (i = 0; i < length; i++) + { + /* + * 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(outputchar, buffer++); + bytes_read++; + } +/* + * Most read functions return the number of bytes put into the buffer + * return 0 would signify end of file + */ +return bytes_read; +} + + +/* + * Called when a process writes to dev file: echo "hi" > /dev/hello + */ +static ssize_t one_write(struct file *filp, const char *buff, size_t len, loff_t * off) + { + printk(KERN_ALERT "Sorry, write isn't supported.\n"); + return -EINVAL; + } + + +module_init(one_init); +module_exit(one_exit); + +MODULE_LICENSE("Some License"); +MODULE_AUTHOR("Matthias Janetschek"); /* Who wrote this module? */ +MODULE_DESCRIPTION("An example module"); /* What does this module do */