Initial commit

This commit is contained in:
2017-10-26 20:06:07 +02:00
commit 816d79f366
2 changed files with 155 additions and 0 deletions
Executable
+14
View File
@@ -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
Executable
+141
View File
@@ -0,0 +1,141 @@
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/fs.h>
#include <asm/uaccess.h> /* 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 */