Linux字符设备驱动--No.3

Posted embeded-linux

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux字符设备驱动--No.3相关的知识,希望对你有一定的参考价值。

字符驱动(按键)初始化函数分析:

 1 int charDrvInit(void)
 2 {
 3     
 4     devNum = MKDEV(reg_major, reg_minor);
 5 
 6     printk(KERN_EMERG"devNum is %d
", devNum);
 7     if(OK == register_chrdev_region(devNum, subDevNum, DEVICE_NAME))
 8     {
 9         printk(KERN_EMERG"register_chrdev_region ok
");
10     }
11     else
12     {
13         printk(KERN_EMERG"register_chrdev_region error
");
14         return ERROR;
15     }
16
 1 /**
 2  * register_chrdev_region() - register a range of device numbers
 3  * @from: the first in the desired range of device numbers; must include
 4  *        the major number.
 5  * @count: the number of consecutive device numbers required
 6  * @name: the name of the device or driver.
 7  *
 8  * Return value is zero on success, a negative error code on failure.
 9  */
10 int register_chrdev_region(dev_t from, unsigned count, const char *name)
11 {
12     struct char_device_struct *cd;
技术图片
1 static struct char_device_struct {
2     struct char_device_struct *next;
3     unsigned int major;
4     unsigned int baseminor;
5     int minorct;
6     char name[64];
7     struct cdev *cdev;        /* will die */
8 } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
struct char_device_struct
13     dev_t to = from + count;
14     dev_t n, next;
15 
16     for (n = from; n < to; n = next) {
17         next = MKDEV(MAJOR(n)+1, 0);
18         if (next > to)
19             next = to;
20         cd = __register_chrdev_region(MAJOR(n), MINOR(n),
21                    next - n, name);
 1 /*
 2  * Register a single major with a specified minor range.
 3  *
 4  * If major == 0 this functions will dynamically allocate a major and return
 5  * its number.
 6  *
 7  * If major > 0 this function will attempt to reserve the passed range of
 8  * minors and will return zero on success.
 9  *
10  * Returns a -ve errno on failure.
11  */
12 static struct char_device_struct *
13 __register_chrdev_region(unsigned int major, unsigned int baseminor,
14                int minorct, const char *name)
15 {
16     struct char_device_struct *cd, **cp;
17     int ret = 0;
18     int i;
19 
20     cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
21     if (cd == NULL)
22         return ERR_PTR(-ENOMEM);
23 
24     mutex_lock(&chrdevs_lock);
25 
26     /* temporary */
//如果主设备号为零,则自动分配主设备号(从大到小)并返回
27     if (major == 0) {
28         for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
29             if (chrdevs[i] == NULL)
30                 break;
31         }
32 
33         if (i == 0) {
34             ret = -EBUSY;
35             goto out;
36         }
37         major = i;
38         ret = major;
39     }
40 
41     cd->major = major;
42     cd->baseminor = baseminor;
43     cd->minorct = minorct;
44     strlcpy(cd->name, name, sizeof(cd->name));
45 
46     i = major_to_index(major);
47 
1 /* index in the above */
2 static inline int major_to_index(unsigned major)
3 {
4     return major % CHRDEV_MAJOR_HASH_SIZE;
5 }

 

48     for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
49         if ((*cp)->major > major ||
50             ((*cp)->major == major &&
51              (((*cp)->baseminor >= baseminor) ||
52               ((*cp)->baseminor + (*cp)->minorct > baseminor))))
53             break;
54 
55     /* Check for overlapping minor ranges.  */
56     if (*cp && (*cp)->major == major) {
57         int old_min = (*cp)->baseminor;
58         int old_max = (*cp)->baseminor + (*cp)->minorct - 1;
59         int new_min = baseminor;
60         int new_max = baseminor + minorct - 1;
61 
62         /* New driver overlaps from the left.  */
63         if (new_max >= old_min && new_max <= old_max) {
64             ret = -EBUSY;
65             goto out;
66         }
67 
68         /* New driver overlaps from the right.  */
69         if (new_min <= old_max && new_min >= old_min) {
70             ret = -EBUSY;
71             goto out;
72         }
73     }
74 
75     cd->next = *cp;
76     *cp = cd;
77     mutex_unlock(&chrdevs_lock);
78     return cd;
79 out:
80     mutex_unlock(&chrdevs_lock);
81     kfree(cd);
82     return ERR_PTR(ret);
83 }

 

 

 

22         if (IS_ERR(cd))
23             goto fail;
24     }
25     return 0;
26 fail:
27     to = n;
28     for (n = from; n < to; n = next) {
29         next = MKDEV(MAJOR(n)+1, 0);
30         kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
31     }
32     return PTR_ERR(cd);
33 }

 

 
17 
18     gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
19     gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
20     
21     gFile->open = butsOpen;
22 //注册设备函数到file_operations结构体gFile
23 
24    //gDev->owner = THIS_MODULE;
25     gFile->owner = THIS_MODULE;
26     cdev_init(gDev, gFile);
27 //在cdev结构体中添加指针指向file_operations结构体gFile
28     cdev_add(gDev, devNum, 3);
29 //建立设备号与cdev结构体联系
30     printk(KERN_EMERG"button driver initial done...
");
31     return 0;
32 }

 

以上是关于Linux字符设备驱动--No.3的主要内容,如果未能解决你的问题,请参考以下文章

Linux字符设备驱动框架

Linux设备驱动开发 新手,创建第一个字符设备驱动时对一些代码的功能不是很了解,能解释一下吗?

从Linux内核LED驱动来理解字符设备驱动开发流程

Linux字符设备驱动

Linux驱动开发:字符设备驱动开发实战

Linux驱动开发:字符设备驱动开发实战