bible/bible.c

122 lines
2.7 KiB
C

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include "bible.h"
MODULE_LICENSE("GPL"); //God's Parables and Liturgy
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 int on_dev_uevent(struct device*, struct kobj_uevent_env*);
#define DEVICE_NAME "bible"
static dev_t devt;
static struct class* device_class;
static struct device* device;
static struct cdev character_device;
static struct file_operations fops = {
.read = device_read,
.open = device_open,
.release = device_release
};
int init_module(void)
{
int result;
if((result = alloc_chrdev_region(&devt, 0, 1, DEVICE_NAME)) < 0)
{
printk(KERN_ALERT "Couldn't alloc chrdev region: %d\n", result);
return result;
}
if((device_class = class_create(THIS_MODULE, DEVICE_NAME)) == NULL)
{
printk(KERN_ALERT "Couldn't create device class\n");
unregister_chrdev_region(devt, 1);
return -1;
}
device_class->dev_uevent = on_dev_uevent;
if((device = device_create(device_class, NULL, devt, NULL, DEVICE_NAME)) == NULL)
{
printk(KERN_ALERT "Couldn't create device\n");
class_destroy(device_class);
unregister_chrdev_region(devt, 1);
return -1;
}
cdev_init(&character_device, &fops);
if((result = cdev_add(&character_device, devt, 1)) < 0)
{
printk(KERN_ALERT "Couldn't add character device\n");
device_destroy(device_class, devt);
class_destroy(device_class);
unregister_chrdev_region(devt, 1);
return result;
}
return 0;
}
void cleanup_module(void)
{
device_destroy(device_class, devt);
class_destroy(device_class);
unregister_chrdev_region(devt, 1);
}
static int on_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
add_uevent_var(env, "DEVMODE=%#o", 0444);
return 0;
}
static int device_open(struct inode *inode, struct file *file)
{
try_module_get(THIS_MODULE);
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
module_put(THIS_MODULE);
return 0;
}
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
{
int i = 0;
if(*offset + length > bible_txt_len)
{
length = bible_txt_len - *offset;
}
for(; i < length; i++)
{
put_user(*(bible_txt + *offset + i), buffer + i);
}
*offset += length;
return i;
}