Framework for registering Linux kernel driver as class device / How to add new class to Linux kernel

Following simple driver code shows, how to add a new class with name “hello_as_class” can be added to linux kernel.

#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/device.h> // for struct class
static struct class hello_class = { .name = "hello_as_class", .owner = THIS_MODULE,
};
static int __init hello_init(void) { class_register(&hello_class); printk(KERN_INFO "Hello, world\n"); return 0;
}
static void __exit hello_exit(void) { class_unregister(&hello_class); printk(KERN_INFO "Goodbye, world\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
 $ vim Makefile 
obj-m += hello.o
all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Compile this driver as,

 $ make 

Now insert the driver as,

 $ sudo insmod ./hello.ko 

We can check whether this driver is inserted or not as,

$ lsmod | grep hello
hello 16384 0 

This driver will create a directory as, /sys/class/hello_as_class

 $ cd /sys/class/hello_as_class 

Now, if we see kernel source code, struct class has been declared in include/linux/device.h as,

/** * struct class - device classes * @name:	Name of the class. * @owner:	The module owner. * @class_groups: Default attributes of this class. * @dev_groups:	Default attributes of the devices that belong to the class. * @dev_kobj:	The kobject that represents this class and links it into the hierarchy. * @dev_uevent:	Called when a device is added, removed from this class, or a *	few other things that generate uevents to add the environment *	variables. * @devnode:	Callback to provide the devtmpfs. * @class_release: Called to release this class. * @dev_release: Called to release the device. * @shutdown_pre: Called at shut-down time before driver shutdown. * @ns_type:	Callbacks so sysfs can detemine namespaces. * @namespace:	Namespace of the device belongs to this class. * @pm:	The default device power management operations of this class. * @p:	The private data of the driver core, no one other than the *	driver core can touch this. * * A class is a higher-level view of a device that abstracts out low-level * implementation details. Drivers may see a SCSI disk or an ATA disk, but, * at the class level, they are all simply disks. Classes allow user space * to work with devices based on what they do, rather than how they are * connected or how they work. */
struct class {	const char	*name;	struct module	*owner;	const struct attribute_group	**class_groups;	const struct attribute_group	**dev_groups;	struct kobject	*dev_kobj;	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);	char *(*devnode)(struct device *dev, umode_t *mode);	void (*class_release)(struct class *class);	void (*dev_release)(struct device *dev);	int (*shutdown_pre)(struct device *dev);	const struct kobj_ns_type_operations *ns_type;	const void *(*namespace)(struct device *dev);	const struct dev_pm_ops *pm;	struct subsys_private *p;
};
extern int __must_check __class_register(struct class *class, struct lock_class_key *key);
extern void class_unregister(struct class *class);
/* This is a #define to keep the compiler from merging different * instances of the __key variable */
#define class_register(class)	\
({	\	static struct lock_class_key __key;	\	__class_register(class, &__key);	\
})

Reference : Kernel.org

Leave a Reply

Your email address will not be published. Required fields are marked *