+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>");
+MODULE_DESCRIPTION("A hello world char device");
+MODULE_VERSION("1.0.0");
+
+static char helloc_message[] = "hello, world\n";
+
+static ssize_t helloc_read(struct file *filp, char __user *buf, size_t len,
+ loff_t *pos)
+{
+ int r;
+ if (*pos >= sizeof(helloc_message))
+ return 0;
+ if (len > sizeof(helloc_message) - *pos)
+ len = sizeof(helloc_message) - *pos;
+ r = copy_to_user(buf, helloc_message + *pos, len);
+ if (r)
+ return -EFAULT;
+ *pos += len;
+ return len;
+}
+
+static struct file_operations helloc_fops = {
+ .owner = THIS_MODULE,
+ .read = helloc_read,
+};
+
+static dev_t dev;
+static struct cdev *cdev;
+
+static int __init helloc_init(void)
+{
+ int r;
+ r = alloc_chrdev_region(&dev, 0, 1, "helloc");
+ if (r)
+ goto out_region;
+ r = -ENOMEM;
+ printk(KERN_INFO "Allocated major number %d\n", MAJOR(dev));
+ cdev = cdev_alloc();
+ if (!cdev)
+ goto out_alloc;
+ cdev->owner = THIS_MODULE;
+ cdev->ops = &helloc_fops;
+ r = cdev_add(cdev, dev, 1);
+ if (r)
+ goto out_add;
+ return 0;
+out_add:
+ kobject_put(&cdev->kobj);
+out_alloc:
+ unregister_chrdev_region(dev, 1);
+out_region:
+ return r;
+}
+
+static void __exit helloc_exit(void)
+{
+ cdev_del(cdev);
+ unregister_chrdev_region(dev, 1);
+}
+
+module_init(helloc_init);
+module_exit(helloc_exit);