guowenxue
2024-12-23 b8e5f60912c77d52214c21e67fa91ec5f522c54c
commit | author | age
b8e5f6 1 /*
G 2  * Copyright (C) 2024 LingYun IoT System Studio
3  * Author: Guo Wenxue <guowenxue@gmail.com>
4  *
5  * A character skeleton driver example in linux kernel.
6  */
7
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>   /* printk() */
11 #include <linux/fs.h>       /* everything... */
12 #include <linux/errno.h>    /* error codes */
13 #include <linux/types.h>    /* size_t */
14 #include <linux/cdev.h>     /* cdev */
15 #include <linux/version.h>  /* kernel version code */
16 #include <linux/moduleparam.h>
17
18 //#define CONFIG_DYNAMIC_ALLOC
19
20 /* device name and major number */
21 #define DEV_NAME         "chrdev"
22
23 #ifdef CONFIG_DYNAMIC_ALLOC
24 #define DEV_MAJOR  0
25 #else
26 #define DEV_MAJOR  79
27 #endif
28
29 int dev_major = DEV_MAJOR;
30 module_param(dev_major, int, S_IRUGO);
31
32 #ifdef CONFIG_DYNAMIC_ALLOC
33 struct cdev   *cdev;
34 #else
35 struct cdev    cdev;
36 #endif
37
38 static int chrdev_open (struct inode *inode, struct file *file)
39 {
40     return 0;
41 }
42
43 static int chrdev_close (struct inode *node, struct file *file)
44 {
45     return 0;
46 }
47
48 static struct file_operations chrdev_fops = {
49     .owner          = THIS_MODULE,
50     .open           = chrdev_open,  /* open()  implementation */
51     .release        = chrdev_close, /* close() implementation */
52 };
53
54 static int __init chrdev_init(void)
55 {
56     dev_t      devno;
57     int        rv;
58
59     /* 1. Allocate device number */
60     if(0 != dev_major)
61     {
62         devno = MKDEV(dev_major, 0);
63         rv = register_chrdev_region(devno, 1, DEV_NAME);
64     }
65     else
66     {
67         rv = alloc_chrdev_region(&devno, 0, 1, DEV_NAME);
68         dev_major = MAJOR(devno);
69     }
70
71     if(rv < 0)
72     {
73         printk(KERN_ERR "%s driver can't use major %d\n", DEV_NAME, dev_major);
74         return -ENODEV;
75     }
76
77     /* 2. Allocate and initialize cdev */
78 #ifdef CONFIG_DYNAMIC_ALLOC
79     cdev = cdev_alloc();
80     if( !cdev )
81     {
82          printk(KERN_ERR "Unable to allocate cdev\n");
83          goto failed1;
84     }
85     cdev_init(cdev, &chrdev_fops);
86 #else
87     cdev_init(&cdev, &chrdev_fops);
88     cdev.owner = THIS_MODULE;
89 #endif
90
91     /* 3. Register cdev to linux kernel */
92 #ifdef CONFIG_DYNAMIC_ALLOC
93     rv = cdev_add(cdev, devno, 1);
94 #else
95     rv = cdev_add(&cdev, devno, 1);
96 #endif
97     if( rv )
98     {
99         rv = -ENODEV;
100         printk(KERN_ERR "%s driver regist failed, rv=%d\n", DEV_NAME, rv);
101         goto failed1;
102     }
103
104     printk(KERN_INFO "%s driver on major[%d] installed.\n", DEV_NAME, dev_major);
105     return 0;
106
107 failed1:
108     unregister_chrdev_region(devno, 1);
109
110     printk(KERN_ERR "%s driver installed failed.\n", DEV_NAME);
111     return rv;
112 }
113
114 static void __exit chrdev_exit(void)
115 {
116 #ifdef CONFIG_DYNAMIC_ALLOC
117     cdev_del(cdev);
118 #else
119     cdev_del(&cdev);
120 #endif
121     unregister_chrdev_region(MKDEV(dev_major,0), 1);
122
123     printk(KERN_INFO "%s driver removed!\n", DEV_NAME);
124     return;
125 }
126
127 module_init(chrdev_init);
128 module_exit(chrdev_exit);
129
130 MODULE_LICENSE("Dual BSD/GPL");
131 MODULE_AUTHOR("GuoWenxue <guowenxue@gmail.com>");