From 01e3a7b3d1c481bf8b6187d90a739327a3f94e87 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Tue, 8 Dec 2009 12:46:10 -0200 Subject: [PATCH] Allow writing to a buffer for our devices. --- helloc.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/helloc.c b/helloc.c index 8c085f3..00ce97d 100644 --- a/helloc.c +++ b/helloc.c @@ -12,9 +12,11 @@ MODULE_AUTHOR("Thadeu Lima de Souza Cascardo "); MODULE_DESCRIPTION("A hello world char device"); MODULE_VERSION("1.0.0"); +#define BUFFER_SIZE 4096 + /* Message buffer we send to upstream */ -static char hello_message[] = "hello, world\n"; -static char goodbye_message[] = "goodbye, world\n"; +static char *hello_message; +static char *goodbye_message; struct message { char *text; @@ -30,10 +32,10 @@ static int helloc_open(struct inode *ino, struct file *filp) return -ENOMEM; if (iminor(ino) == 0) { msg->text = hello_message; - msg->len = sizeof(hello_message); + msg->len = BUFFER_SIZE; } else { msg->text = goodbye_message; - msg->len = sizeof(goodbye_message); + msg->len = BUFFER_SIZE; } filp->private_data = msg; return 0; @@ -67,12 +69,34 @@ static ssize_t helloc_read(struct file *filp, char __user *buf, size_t len, return len; } +static ssize_t helloc_write(struct file *filp, const 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 >= msg->len) + /* return end of file */ + return 0; + /* if len is bigger than the rest of the message, clamp it */ + if (len > msg->len - *pos) + len = msg->len - *pos; + /* copy message to user space and return error if it fails */ + r = copy_from_user(msg->text + *pos, buf, len); + if (r) + return -EFAULT; + /* update the file position */ + *pos += len; + return len; +} + /* we only implement read */ static struct file_operations helloc_fops = { .owner = THIS_MODULE, .open = helloc_open, .release = helloc_release, .read = helloc_read, + .write = helloc_write, }; /* the device number and the char device struct */ @@ -81,8 +105,14 @@ static struct cdev *cdev; static int __init helloc_init(void) { - int r; + int r = -ENOMEM; /* allocate any major number with only one minor */ + hello_message = kzalloc(BUFFER_SIZE, GFP_KERNEL); + if (!hello_message) + goto out_hello; + goodbye_message = kzalloc(BUFFER_SIZE, GFP_KERNEL); + if (!goodbye_message) + goto out_goodbye; r = alloc_chrdev_region(&dev, 0, 2, "helloc"); if (r) goto out_region; @@ -108,6 +138,10 @@ out_alloc: /* release the device number allocated */ unregister_chrdev_region(dev, 2); out_region: + kfree(goodbye_message); +out_goodbye: + kfree(hello_message); +out_hello: return r; } @@ -117,6 +151,8 @@ static void __exit helloc_exit(void) cdev_del(cdev); /* release the device number allocated */ unregister_chrdev_region(dev, 2); + kfree(goodbye_message); + kfree(hello_message); } module_init(helloc_init); -- 2.20.1