#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
// thx http://lwn.net/Kernel/LDD3/
static char* txt[] =
{
"Welcome to my new blog; perhaps you have visisted my former blog at spin.de, too. This is it's successor!\n"
"Have a lot of fun, btwotch\n",
"http://twitter.com/btwotch\n",
"http://btwotch.soup.io\n",
"http://mister-wong.de/user/btwotch\n"
};
static dev_t d;
static struct cdev* c;
struct txt_msg
{
size_t written;
char *txt;
size_t txt_len;
};
static int btwotch_open(struct inode* i, struct file* f)
{
int minor = iminor(f->f_dentry->d_inode);
struct txt_msg *tm = kmalloc(sizeof(struct txt_msg), GFP_KERNEL);
tm->written = 0;
if (minor > 4)
minor = 0;
tm->txt = txt[minor];
tm->txt_len = strlen(tm->txt);
f->private_data = tm;
return 0;
}
static int btwotch_close(struct inode* i, struct file* f)
{
kfree(f->private_data);
return 0;
}
static ssize_t btwotch_read(struct file* f, char __user *user, size_t count, loff_t *offset)
{
size_t len, leftwrite, written;
struct txt_msg *tm = (struct txt_msg*)f->private_data;
if (tm->txt_len == tm->written) // that's how we do EOF!
return 0;
leftwrite = tm->txt_len-tm->written;
len = (count < leftwrite) ? count : leftwrite;
written = copy_to_user(user, tm->txt+tm->written, len);
tm->written += len-written;
return len-written;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.read = btwotch_read,
.open = btwotch_open,
.release = btwotch_close
};
static void register_driver(void)
{
c = cdev_alloc();
cdev_init(c, &fops);
alloc_chrdev_region(&d, 0, 5, "btwotch-drv");
cdev_add(c, d, 1);
cdev_add(c, d, 2);
cdev_add(c, d, 3);
cdev_add(c, d, 4);
printk("btwotch-mod: major: %d minor: %d\n", MAJOR(d), MINOR(d));
}
static void unregister_driver(void)
{
cdev_del(c);
unregister_chrdev_region(d, 5);
}
static int __init init_btwotch(void)
{
register_driver();
return 0;
}
static void __exit cleanup_btwotch(void)
{
unregister_driver();
}
module_init(init_btwotch);
module_exit(cleanup_btwotch);
MODULE_AUTHOR("btwotch");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("the btwotch virtual device");
MODULE_SUPPORTED_DEVICE("none");