From 2fa0b3e1817228b3d23741a06ed044cdf66ccc88 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Tue, 8 Dec 2009 10:49:25 -0200 Subject: [PATCH] Implemented open/release with multiple devices. --- helloc.c | 52 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/helloc.c b/helloc.c index 0db07e3..8c085f3 100644 --- a/helloc.c +++ b/helloc.c @@ -5,6 +5,7 @@ #include /* Needed for copying to/from user space */ #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Thadeu Lima de Souza Cascardo "); @@ -12,22 +13,53 @@ MODULE_DESCRIPTION("A hello world char device"); MODULE_VERSION("1.0.0"); /* Message buffer we send to upstream */ -static char helloc_message[] = "hello, world\n"; +static char hello_message[] = "hello, world\n"; +static char goodbye_message[] = "goodbye, world\n"; + +struct message { + char *text; + size_t len; +}; + +static int helloc_open(struct inode *ino, struct file *filp) +{ + struct message *msg; + printk(KERN_INFO "Opened file with minor %d\n", iminor(ino)); + msg = kmalloc(sizeof(struct message), GFP_KERNEL); + if (!msg) + return -ENOMEM; + if (iminor(ino) == 0) { + msg->text = hello_message; + msg->len = sizeof(hello_message); + } else { + msg->text = goodbye_message; + msg->len = sizeof(goodbye_message); + } + filp->private_data = msg; + return 0; +} + +static int helloc_release(struct inode *ino, struct file *filp) +{ + kfree(filp->private_data); + return 0; +} /* our read function writes our message to the user buffer */ static ssize_t helloc_read(struct file *filp, char __user *buf, size_t len, loff_t *pos) { int r; + struct message *msg = filp->private_data; /* do not read pass through the size of the message */ - if (*pos >= sizeof(helloc_message)) + if (*pos >= msg->len) /* return end of file */ return 0; /* if len is bigger than the rest of the message, clamp it */ - if (len > sizeof(helloc_message) - *pos) - len = sizeof(helloc_message) - *pos; + if (len > msg->len - *pos) + len = msg->len - *pos; /* copy message to user space and return error if it fails */ - r = copy_to_user(buf, helloc_message + *pos, len); + r = copy_to_user(buf, msg->text + *pos, len); if (r) return -EFAULT; /* update the file position */ @@ -38,6 +70,8 @@ static ssize_t helloc_read(struct file *filp, char __user *buf, size_t len, /* we only implement read */ static struct file_operations helloc_fops = { .owner = THIS_MODULE, + .open = helloc_open, + .release = helloc_release, .read = helloc_read, }; @@ -49,7 +83,7 @@ static int __init helloc_init(void) { int r; /* allocate any major number with only one minor */ - r = alloc_chrdev_region(&dev, 0, 1, "helloc"); + r = alloc_chrdev_region(&dev, 0, 2, "helloc"); if (r) goto out_region; r = -ENOMEM; @@ -63,7 +97,7 @@ static int __init helloc_init(void) cdev->owner = THIS_MODULE; cdev->ops = &helloc_fops; /* register the chardev to the system */ - r = cdev_add(cdev, dev, 1); + r = cdev_add(cdev, dev, 2); if (r) goto out_add; return 0; @@ -72,7 +106,7 @@ out_add: kfree(cdev); out_alloc: /* release the device number allocated */ - unregister_chrdev_region(dev, 1); + unregister_chrdev_region(dev, 2); out_region: return r; } @@ -82,7 +116,7 @@ static void __exit helloc_exit(void) /* remove the chardev from the system */ cdev_del(cdev); /* release the device number allocated */ - unregister_chrdev_region(dev, 1); + unregister_chrdev_region(dev, 2); } module_init(helloc_init); -- 2.20.1