First character device.
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Sun, 6 Dec 2009 20:22:25 +0000 (18:22 -0200)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Sun, 6 Dec 2009 20:22:25 +0000 (18:22 -0200)
This version uses a kobject_put in an error path, which students may not know
about yet.

Makefile [new file with mode: 0644]
helloc.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..76d1323
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+ifneq ($(KERNELRELEASE),)
+       obj-m := helloc.o
+else
+       KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+       PWD := $(shell pwd)
+default:
+       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+       $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+endif
diff --git a/helloc.c b/helloc.c
new file mode 100644 (file)
index 0000000..4d99fcb
--- /dev/null
+++ b/helloc.c
@@ -0,0 +1,68 @@
+#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);