#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/dma-mapping.h>
//定義設備名稱為test-dev
#define DEV_NAME "test-dev"
//定義並初始化一個類
struct class cla = {
.name = "test-cla", //將類的名字設置為test-cla
.owner = THIS_MODULE, //該類的擁有者為這個模塊
};
int test_open(struct inode *node, struct file *filp)
{
printk("test open\n");
return 0;
}
int test_close(struct inode *node, struct file *filp)
{
printk("test close\n");
return 0;
}
//填充並初始化file_operations結構體
struct file_operations fops = {
.owner = THIS_MODULE,
.open = test_open,
.release = test_close,
};
//定義設備
struct device dev = {
.init_name = DEV_NAME,
.class = &cla, //設備歸類cla;
.release = test_release,
};
//定義主設備號和次設備號
int major = 0;
int minor = 0;
int test_init(void)
{
int ret;
printk("test init\n");
//將類進行注冊
ret = class_register(&cla);
//如果返回值不為0,返回錯誤值
if(IS_ERR_VALUE(ret))
{
return ret;
}
//注冊一個字符設備驅動
ret = register_chrdev(major, DEV_NAME, &fops);
//如果注冊不成功返回錯誤值並撤銷類的實現
if(IS_ERR_VALUE(ret))
{
class_unregister(&cla);
return ret;
}
major = ret;
//printk("major = %d\n", major);
//申請主設備號與次設備號
dev.devt = MKDEV(major, minor);
//將設備進行注冊
ret = device_register(&dev);
//如果設備注冊不成功,撤銷類設備注冊並解除字符設備驅動的注冊
if(IS_ERR_VALUE(ret))
{
class_unregister(&cla);
unregister_chrdev(major, DEV_NAME);
return ret;
}
return 0;
}
void test_exit(void)
{
printk("test exit\n");
//解除字符設備的注冊
unregister_chrdev(major, DEV_NAME);
//解決類設備注冊
device_unregister(&dev);
class_unregister(&cla);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("yangyx");
MODULE_VERSION("1.1");