linuxdebug/drivers/vogon/vogon.c

119 lines
3.0 KiB
C

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/printk.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/spinlock.h>
#define VOGON_CHRDEV "vogon"
static char *poem[] = {
"Oh freddled gruntbuggly,",
"Thy micturations are to me, (with big yawning)",
"As plurdled gabbleblotchits, in midsummer morning",
"On a lurgid bee,",
"That mordiously hath blurted out,",
"Its earted jurtles, grumbling",
"Into a rancid festering confectious organ squealer. [drowned out by moaning and screaming]",
"Now the jurpling slayjid agrocrustles,",
"Are slurping hagrilly up the axlegrurts,",
"And living glupules frart and stipulate,",
"Like jowling meated liverslime,",
"Groop, I implore thee, my foonting turlingdromes,",
"And hooptiously drangle me,",
"With crinkly bindlewurdles,mashurbitries.",
"Or else I shall rend thee in the gobberwarts with my blurglecruncheon,",
"See if I don't!",
NULL
};
static int poem_len, poem_line;
static spinlock_t poem_lock;
static int vogon_chrdev_major = 0;
static struct device *my_dev = NULL;
void vogon_poem_inc(void) {
spin_lock(&poem_lock);
if (poem[poem_line] == NULL) {
poem_line = 0;
}else {
poem_line++;
}
spin_unlock(&poem_lock);
}
static int vogon_peom(struct seq_file *p, void *v) {
int i;
// In the dusk of an Operating System, the solution lies beyond its bounds.
spin_lock_bh(&poem_lock);
i = poem_line;
spin_unlock_bh(&poem_lock);
seq_printf(p, "%s\n", poem[i]);
return 0;
}
static int vogon_open(struct inode *inode, struct file *file) {
return single_open(file, vogon_peom, NULL);
}
const struct file_operations vogon_fops = {
.owner = THIS_MODULE,
.open = vogon_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release
};
static struct class universe_class = {
.name = VOGON_CHRDEV,
};
static int __init vogon_chrdevinit(void) {
int err;
for (int i = 0; poem[i]; i++) {
poem_len++;
}
spin_lock_init(&poem_lock);
vogon_chrdev_major = err = register_chrdev(0, VOGON_CHRDEV, &vogon_fops);
if (err < 0) {
pr_err("Cannot register chrdev: %d\n", err);
goto out;
}
err = class_register(&universe_class);
if (err) {
pr_err("Cannot register universe class: %d\n", err);
goto out_chrdev;
}
my_dev = device_create(&universe_class, NULL, MKDEV(vogon_chrdev_major, 0), NULL, VOGON_CHRDEV);
if (IS_ERR(my_dev)) {
err = PTR_ERR(my_dev);
pr_err("Cannot create device: %d\n", err);
goto out_class;
}
pr_notice("Loaded module %s\n", KBUILD_MODNAME);
return 0;
out_class:
class_unregister(&universe_class);
out_chrdev:
unregister_chrdev(vogon_chrdev_major, VOGON_CHRDEV);
out:
return err;
}
static void __exit vogon_chrdevexit(void) {
device_destroy(&universe_class, MKDEV(vogon_chrdev_major, 0));
class_unregister(&universe_class);
unregister_chrdev(vogon_chrdev_major, VOGON_CHRDEV);
pr_notice("Unloaded module %s\n", KBUILD_MODNAME);
}
module_init(vogon_chrdevinit);
module_exit(vogon_chrdevexit);
MODULE_LICENSE("LGPL");