diff options
author | lonkaars <loek@pipeframe.xyz> | 2024-04-18 17:34:40 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2024-04-18 17:34:40 +0200 |
commit | bfb105b36e902ffc1aec9424a38245db693eea02 (patch) | |
tree | 33cb1b9c5d2002ce1c76dc3575760e3c6a57f125 | |
parent | 2d8b061d0f442d8a8853025460a836e3482cc09b (diff) |
dynamically get major:minor numbers + register /dev node + /sys/class node
-rw-r--r-- | 1/config.h | 3 | ||||
-rw-r--r-- | 1/main.c | 42 | ||||
-rw-r--r-- | readme.md | 8 |
3 files changed, 44 insertions, 9 deletions
@@ -1,5 +1,4 @@ #pragma once -#define NODE_MAJOR 500 -#define NODE_MINOR 0 +#define DRV_NAME "lork" @@ -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"); @@ -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 |