aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2024-04-18 17:34:40 +0200
committerlonkaars <loek@pipeframe.xyz>2024-04-18 17:34:40 +0200
commitbfb105b36e902ffc1aec9424a38245db693eea02 (patch)
tree33cb1b9c5d2002ce1c76dc3575760e3c6a57f125
parent2d8b061d0f442d8a8853025460a836e3482cc09b (diff)
dynamically get major:minor numbers + register /dev node + /sys/class node
-rw-r--r--1/config.h3
-rw-r--r--1/main.c42
-rw-r--r--readme.md8
3 files changed, 44 insertions, 9 deletions
diff --git a/1/config.h b/1/config.h
index 1d15f75..7302134 100644
--- a/1/config.h
+++ b/1/config.h
@@ -1,5 +1,4 @@
#pragma once
-#define NODE_MAJOR 500
-#define NODE_MINOR 0
+#define DRV_NAME "lork"
diff --git a/1/main.c b/1/main.c
index 66ceac4..101f675 100644
--- a/1/main.c
+++ b/1/main.c
@@ -6,6 +6,9 @@
#include "config.h"
struct cdev *cdev;
+struct device *dev;
+struct class *class;
+dev_t node;
struct file_operations fops = {
.read = fop_read,
.write = fop_write,
@@ -15,38 +18,63 @@ struct file_operations fops = {
static int mod_init(void) {
int err;
- cdev = cdev_alloc();
- dev_t node = MKDEV(NODE_MAJOR, NODE_MINOR);
+ err = alloc_chrdev_region(&node, 0, 1, DRV_NAME);
+ if (err < 0) {
+ printk(KERN_ERR "alloc_chrdev_region error %d\n", err);
+ goto return_err;
+ }
+
+ class = class_create(DRV_NAME);
+ if (IS_ERR_OR_NULL(class)) {
+ err = PTR_ERR(class);
+ printk(KERN_ERR "class_create error %d\n", err);
+ goto free_class;
+ }
+
+ cdev = cdev_alloc();
if (!cdev) {
err = ENOMEM;
goto free_cdev;
}
cdev->ops = &fops;
-
+ cdev_init(cdev, &fops);
err = cdev_add(cdev, node, 1);
if (err < 0) {
- printk(KERN_ERR "cdev_add failed w/ error code %d\n", err);
+ printk(KERN_ERR "cdev_add error %d\n", err);
goto free_cdev;
}
- printk("%s\n", __PRETTY_FUNCTION__);
+ dev = device_create(class, NULL, node, NULL, DRV_NAME);
+ if (IS_ERR_OR_NULL(dev)) {
+ err = PTR_ERR(dev);
+ printk(KERN_ERR "device_create error %d\n", err);
+ goto free_device;
+ }
+
+ printk("%s %d:%d\n", __PRETTY_FUNCTION__, MAJOR(node), MINOR(node));
return 0;
+free_device:
+ device_destroy(class, node);
free_cdev:
cdev_del(cdev);
-
+free_class:
+ class_destroy(class);
+return_err:
printk("%s: %d\n", __PRETTY_FUNCTION__, err);
return err;
}
static void mod_exit(void) {
+ device_destroy(class, node);
cdev_del(cdev);
+ class_destroy(class);
printk("%s\n", __PRETTY_FUNCTION__);
}
module_init(mod_init);
module_exit(mod_exit);
-MODULE_LICENSE("MIT");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/readme.md b/readme.md
index f8f735d..267fc38 100644
--- a/readme.md
+++ b/readme.md
@@ -1,5 +1,7 @@
# sources
+(ordered chronologically by access time)
+
- [Kbuild object variable name rationale][kbuild-obj-var]
- [Kbuild kernel module setup guide][kbuild-module-makefile]
- [`struct file_operations`][c-struct-file-operations] documentation, also
@@ -8,11 +10,17 @@
- (Sadly) [the Linux kernel source][kernel] itself, especially
- drivers/char/random.c
- drivers/char/mem.c
+- [Linux kernel labs - character device drivers][kernel-labs-chrdev]
+- [Core API][core-api]
+- [Driver API][driver-api]
[kbuild-obj-var]: https://docs.kernel.org/kbuild/makefiles.html#loadable-module-goals-obj-m
[kbuild-module-makefile]: https://www.kernel.org/doc/html/latest/kbuild/modules.html#creating-a-kbuild-file-for-an-external-module
[c-struct-file-operations]: https://www.kernel.org/doc/html/latest/filesystems/vfs.html#struct-file-operations
[kernel]: https://github.com/torvalds/linux
+[kernel-labs-chrdev]: https://linux-kernel-labs.github.io/refs/heads/master/labs/device_drivers.html
+[core-api]: https://docs.kernel.org/core-api/kernel-api.html
+[driver-api]: https://www.kernel.org/doc/html/latest/driver-api/infrastructure.html
# tips