diff options
Diffstat (limited to 'char.c')
| -rw-r--r-- | char.c | 92 | 
1 files changed, 92 insertions, 0 deletions
@@ -0,0 +1,92 @@ +#include "char.h" + +#include "linux/cdev.h" +#include "linux/device.h" +#include "linux/fs.h" + +#include "util.h" + +#define DOOMDEV_COUNT 256 +#define DOOMDEV_NAME "doom" + +dev_t first; +int major; +int next_minor = 0; + +long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ +	return -1; +} + +int doom_open(struct inode *inode, struct file *filp) +{ +	return -1; +} + +struct file_operations doomdev_fops = { +	.owner = THIS_MODULE, +	.unlocked_ioctl = doom_ioctl, +	.compat_ioctl = doom_ioctl, +	.open = doom_open +}; +	 +struct class *doom_class; + +int new_doomdev(void) +{ +	int err = 0; +	int minor; +	dev_t devt; +	struct cdev *doom_cdev; +	struct device *doomdev; +	if (next_minor >= DOOMDEV_COUNT) { +		return -ENOMEM; +	} + +	doom_cdev = cdev_alloc(); +	if (doom_cdev == NULL) { +		return -ENOMEM; +	} + +	doom_cdev->ops = &doomdev_fops; +	ORFAIL(cdev_add(doom_cdev, first, 1), error_add); +	minor = next_minor++; +	devt = MKDEV(major, minor); +	ORFAIL_PTR(device_create(doom_class, NULL, devt, NULL, +				"doom%d", minor), +			doomdev, error_create); + +error_create: +	cdev_del(doom_cdev); +error_add: +	return err; +} + +void destroy_doomdev(void) +{ +	device_destroy(doom_class, first); +} + +int char_init(void) +{ +	int err = 0; +	ORFAIL(alloc_chrdev_region(&first, 0, DOOMDEV_COUNT, DOOMDEV_NAME), +			error_region); +	major = MAJOR(first); +	doom_class = class_create(THIS_MODULE, "doom"); +	if (IS_ERR(doom_class)) { +		err = PTR_ERR(doom_class); +		goto error_create; +	} + +error_create: +	unregister_chrdev_region(first, DOOMDEV_COUNT); +error_region: +	return err; +} + +void char_cleanup(void) +{ +	unregister_chrdev_region(first, DOOMDEV_COUNT); +	class_unregister(doom_class); +}  |