1 #include <linux/module.h>
2 /* Needed for struct file_operations and others */
4 /* Needed for struct cdev */
5 #include <linux/cdev.h>
6 /* Needed for copying to/from user space */
7 #include <asm/uaccess.h>
8 #include <linux/slab.h>
10 MODULE_LICENSE("GPL");
11 MODULE_AUTHOR("Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>");
12 MODULE_DESCRIPTION("A hello world char device");
13 MODULE_VERSION("1.0.0");
15 #define BUFFER_SIZE 4096
17 /* Message buffer we send to upstream */
18 static char *hello_message;
19 static char *goodbye_message;
26 static int helloc_open(struct inode *ino, struct file *filp)
29 printk(KERN_INFO "Opened file with minor %d\n", iminor(ino));
30 msg = kmalloc(sizeof(struct message), GFP_KERNEL);
33 if (iminor(ino) == 0) {
34 msg->text = hello_message;
35 msg->len = BUFFER_SIZE;
37 msg->text = goodbye_message;
38 msg->len = BUFFER_SIZE;
40 filp->private_data = msg;
44 static int helloc_release(struct inode *ino, struct file *filp)
46 kfree(filp->private_data);
50 /* our read function writes our message to the user buffer */
51 static ssize_t helloc_read(struct file *filp, char __user *buf, size_t len,
55 struct message *msg = filp->private_data;
56 /* do not read pass through the size of the message */
58 /* return end of file */
60 /* if len is bigger than the rest of the message, clamp it */
61 if (len > msg->len - *pos)
62 len = msg->len - *pos;
63 /* copy message to user space and return error if it fails */
64 r = copy_to_user(buf, msg->text + *pos, len);
67 /* update the file position */
72 static ssize_t helloc_write(struct file *filp, const char __user *buf,
73 size_t len, loff_t *pos)
76 struct message *msg = filp->private_data;
77 /* do not read pass through the size of the message */
79 /* return end of file */
81 /* if len is bigger than the rest of the message, clamp it */
82 if (len > msg->len - *pos)
83 len = msg->len - *pos;
84 /* copy message to user space and return error if it fails */
85 r = copy_from_user(msg->text + *pos, buf, len);
88 /* update the file position */
93 /* we only implement read */
94 static struct file_operations helloc_fops = {
97 .release = helloc_release,
99 .write = helloc_write,
102 /* the device number and the char device struct */
104 static struct cdev *cdev;
106 static int __init helloc_init(void)
109 /* allocate any major number with only one minor */
110 hello_message = kzalloc(BUFFER_SIZE, GFP_KERNEL);
113 goodbye_message = kzalloc(BUFFER_SIZE, GFP_KERNEL);
114 if (!goodbye_message)
116 r = alloc_chrdev_region(&dev, 0, 2, "helloc");
120 /* print the major number allocated so we can create our device node */
121 printk(KERN_INFO "Allocated major number %d\n", MAJOR(dev));
122 /* allocate the character device struct */
126 /* set the module owner and the file operations of our chardev */
127 cdev->owner = THIS_MODULE;
128 cdev->ops = &helloc_fops;
129 /* register the chardev to the system */
130 r = cdev_add(cdev, dev, 2);
135 /* release memory allocated to the cdev device */
138 /* release the device number allocated */
139 unregister_chrdev_region(dev, 2);
141 kfree(goodbye_message);
143 kfree(hello_message);
148 static void __exit helloc_exit(void)
150 /* remove the chardev from the system */
152 /* release the device number allocated */
153 unregister_chrdev_region(dev, 2);
154 kfree(goodbye_message);
155 kfree(hello_message);
158 module_init(helloc_init);
159 module_exit(helloc_exit);