#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/miscdevice.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>");
MODULE_VERSION("1.0.0");
#define BUFFER_SIZE 4096
-#define DEVICE_NUMBER 2
struct message {
char *text;
};
/* Message buffer we send to upstream */
-static struct message *hello_message[DEVICE_NUMBER];
+static struct message *hello_message;
static int helloc_open(struct inode *ino, struct file *filp)
{
struct message *msg;
printk(KERN_INFO "Opened file with minor %d\n", iminor(ino));
- if (iminor(ino) >= DEVICE_NUMBER)
- return -ENODEV;
- msg = hello_message[iminor(ino)];
+ msg = hello_message;
filp->private_data = msg;
if (filp->f_flags & O_TRUNC) {
memset(msg->text, 0, msg->len);
static int hello_proc_open(struct inode *ino, struct file *filp)
{
- return single_open(filp, hello_len_show, hello_message[0]);
+ return single_open(filp, hello_len_show, hello_message);
}
static struct file_operations hello_proc_fops = {
.release = seq_release,
};
-
-/* the device number and the char device struct */
-static dev_t dev;
-static struct cdev *cdev;
-
static void helloc_free(void)
{
- int i;
- for (i = 0; i < DEVICE_NUMBER; i++) {
- if (hello_message[i])
- kfree(hello_message[i]->text);
- kfree(hello_message[i]);
- }
+ if (hello_message)
+ kfree(hello_message->text);
+ kfree(hello_message);
}
static int __init helloc_alloc(void)
{
- int i;
- for (i = 0; i < DEVICE_NUMBER; i++) {
- hello_message[i] = kzalloc(sizeof(struct message), GFP_KERNEL);
- if (!hello_message[i])
- goto out;
- hello_message[i]->text = kzalloc(BUFFER_SIZE, GFP_KERNEL);
- if (!hello_message[i]->text)
- goto out;
- }
+ hello_message = kzalloc(sizeof(struct message), GFP_KERNEL);
+ if (!hello_message)
+ return -ENOMEM;
+ hello_message->text = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+ if (!hello_message->text)
+ goto out;
return 0;
out:
- for (; i >= 0; i--) {
- if (hello_message[i])
- kfree(hello_message[i]->text);
- kfree(hello_message[i]);
- }
+ kfree(hello_message);
return -ENOMEM;
}
+static struct miscdevice hello_misc = {
+ .name = "hello",
+ .fops = &helloc_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
static int __init helloc_init(void)
{
struct proc_dir_entry *hello_pde;
int r;
r = helloc_alloc();
if (r)
- goto out_alloc2;
- /* allocate any major number with only one minor */
- r = alloc_chrdev_region(&dev, 0, DEVICE_NUMBER, "helloc");
- if (r)
- goto out_region;
- r = -ENOMEM;
- /* print the major number allocated so we can create our device node */
- printk(KERN_INFO "Allocated major number %d\n", MAJOR(dev));
- /* allocate the character device struct */
- cdev = cdev_alloc();
- if (!cdev)
goto out_alloc;
- /* set the module owner and the file operations of our chardev */
- cdev->owner = THIS_MODULE;
- cdev->ops = &helloc_fops;
- /* register the chardev to the system */
- r = cdev_add(cdev, dev, DEVICE_NUMBER);
+ r = misc_register(&hello_misc);
if (r)
- goto out_add;
+ goto out_reg;
hello_pde = proc_create("hello_len", 0666, NULL, &hello_proc_fops);
if (!hello_pde)
goto out_pde;
return 0;
out_pde:
- cdev_del(cdev);
-out_add:
- /* release memory allocated to the cdev device */
- kfree(cdev);
+ misc_deregister(&hello_misc);
+out_reg:
out_alloc:
- /* release the device number allocated */
- unregister_chrdev_region(dev, DEVICE_NUMBER);
-out_region:
-out_alloc2:
return r;
}
static void __exit helloc_exit(void)
{
remove_proc_entry("hello_len", NULL);
- /* remove the chardev from the system */
- cdev_del(cdev);
- /* release the device number allocated */
- unregister_chrdev_region(dev, DEVICE_NUMBER);
+ misc_deregister(&hello_misc);
helloc_free();
}