LDD 3rd 中文版实在是让我忍无可忍,USB驱动一章翻译得那是相当的晦涩,看得我云里雾里,索性扔下书来看代码,以后主要靠自己分析代码学习,多读网上前辈的笔记,这样不仅能加深对代码的理解,也看到了别人的思维角度,比抱着LDD 3rd啃强多了,开搞!

新手自学笔记,比较罗嗦,冗长,学到什么地方就写到什么地方,没有具体的层次和顺序。写这个笔记的目的,仅仅是当作备忘和一个过程的记录,如果高手看到了谬误之处,敬请斧正。

全部代码、笔记、实验都在Debian GNU/Linux 下进行,内核版本如下:

ganquan@debian:~$ uname -r

2.6.26-2-686

0.先从阅读usb-skeleton.c开始

ganquan@debian:~$ cat /usr/src/linux-source-2.6.26/drivers/usb/usb-skeleton.c | wc -l

525

还好,只有525行。不算吓人。

从驱动程序的Hello World开始看:

504    static int __init usb_skel_init(void)
 
505    {
 
506        int result;
 
507
 
508        /* register this driver with the USB subsystem */
 
509        result = usb_register(&skel_driver);
 
510        if (result)
 
511            err("usb_register failed. Error number %d", result);
 
512
 
513        return result;
 
514    }
 
515
 
516    static void __exit usb_skel_exit(void)
 
517    {
 
518        /* deregister this driver with the USB subsystem */
 
519        usb_deregister(&skel_driver);
 
520    }

显然的,504行的usb_skel_init(void)就是insmod之后被运行的初始化函数,它只干了一件事:调用usb_register函数,注册了一个叫skel_driver的东西,skel_driver是在usb-skeleton.c 文件67行定义的一个usb_driver类型的结构体。再来看看usb_driver到底是何方妖孽。

在linux-source-2.6.26/include/linux/usb.h里面,991行到1015行定义了这个结构体如下:

991 struct usb_driver {
 
992 const char *name;
 
993
 
994 int (*probe) (struct usb_interface *intf,
 
995 const struct usb_device_id *id);
 
996
 
997 void (*disconnect) (struct usb_interface *intf);
 
998
 
999 int (*ioctl) (struct usb_interface *intf, unsigned int code,
 
1000 void *buf);
 
1001
 
1002 int (*suspend) (struct usb_interface *intf, pm_message_t message);
 
1003 int (*resume) (struct usb_interface *intf);
 
1004 int (*reset_resume)(struct usb_interface *intf);
 
1005
 
1006 int (*pre_reset)(struct usb_interface *intf);
 
1007 int (*post_reset)(struct usb_interface *intf);
 
1008
 
1009 const struct usb_device_id *id_table;
 
1010
 
1011 struct usb_dynids dynids;
 
1012 struct usbdrv_wrap drvwrap;
 
1013 unsigned int no_dynamic_id:1;
 
1014 unsigned int supports_autosuspend:1;
 
1015 };

可见这个结构体包含了不少函数指针,通过名字大概猜了一下各个回调函数里面应该干啥,结构体中各个字段在内核代码中都有详细注释,不再一一叙述。总之,这个结构体现在看来,是用于标识我的USB驱动程序的。

搞清楚了传递给usb_register函数的参数,再看来看这个函数是干啥的。

还是在linux-source-2.6.26/include/linux/usb.h里面,有:

1075 static inline int usb_register(struct usb_driver *driver)
 
1076 {
 
1077 return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
 
1078 }

这个内联函数居然又调用了另外一个函数,内核真是一个蜘蛛网,一点也不假,继续看:

usb_register_driver函数,第一个参数是用来标识USB驱动程序的usb_driver类型的结构体,第二、三个参数都是宏,但是第二个参数其实是一个module类型的结构体,第三个参数是字符指针,这两个参数暂时不分析。先放着就可以了。

接下来看一下usb_register_driver函数又干了什么。

在linux-source-2.6.26/driver/usb/core/driver.c中:

715 int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
 
716 const char *mod_name)
 
717 {
 
718 int retval = 0;
 
719
 
720 if (usb_disabled())
 
721 return -ENODEV;
 
722
 
723 new_driver->drvwrap.for_devices = 0;
 
724 new_driver->drvwrap.driver.name = (char *) new_driver->name;
 
725 new_driver->drvwrap.driver.bus = &usb_bus_type;
 
726 new_driver->drvwrap.driver.probe = usb_probe_interface;
 
727 new_driver->drvwrap.driver.remove = usb_unbind_interface;
 
728 new_driver->drvwrap.driver.owner = owner;
 
729 new_driver->drvwrap.driver.mod_name = mod_name;
 
730 spin_lock_init(&new_driver->dynids.lock);
 
731 INIT_LIST_HEAD(&new_drive->dynids.list);
 
732
 
733 retval = driver_register(&new_driver->drvwrap.driver);
 
734
 
735 if (!retval) {
 
736 pr_info("%s: registered new interface driver %s\n",
 
737 usbcore_name, new_driver->name);
 
738 usbfs_update_special();
 
739 usb_create_newid_file(new_driver);
 
740 } else {
 
741 printk(KERN_ERR "%s: error %d registering interface "
 
742 " driver %s\n",
 
743 usbcore_name, retval, new_driver->name);
 
744 }
 
745
 
746 return retval;
 
747 }

以上可见usb_register_driver函数中对usb_driver结构体的一个成员赋值,也就是对drvwrap成员。drvwrap是一个结构体,函数中对它的driver成员的各个字段进行赋值,并且usb_register_driver函数中还调用了一个driver_register函数,传入参数是drvwap的driver字段,看来这个drvwap成员分量不轻,现在去探究一下 这个usbdrv_wrap类型的drvwrap又是什么。

在linux-source-2.6.26/include/linux/usb.h中:

934 struct usbdrv_wrap {
 
935 struct device_driver driver;
 
936 int for_devices;
 
937 };

可见,usbdrv_wrap只不过是一个对device_driver的封装,继续深入看一下device_driver又是什么。

在linux-source-2.6.26/include/linux/device.h中:

120 struct device_driver {
 
121 const char *name;
 
122 struct bus_type *bus;
 
123
 
124 struct module *owner;
 
125 const char *mod_name; /* used for built-in modules */
 
126
 
127 int (*probe) (struct device *dev);
 
128 int (*remove) (struct device *dev);
 
129 void (*shutdown) (struct device *dev);
 
130 int (*suspend) (struct device *dev, pm_message_t state);
 
131 int (*resume) (struct device *dev);
 
132 struct attribute_group **groups;
 
133
 
134 struct driver_private *p;
 
135 };

注意到device_driver的定义,134行又是一个driver_private结构体指针。非常有必要弄清楚这个结构体。

在linux-source-2.6.26/driver/base/base.h中,有:

30 struct driver_private {
 
31 struct kobject kobj;
 
32 struct klist klist_devices;
 
33 struct klist_node knode_bus;
 
34 struct module_kobject *mkobj;
 
35 struct device_driver *driver;
 
36 };

继续深入看看kobject又长什么样子。

在linux-source-2.6.26/include/linux/kobject.h中:

60 struct kobject {
 
61 const char *name;
 
62 struct kref kref;
 
63 struct list_head entry;
 
64 struct kobject *parent;
 
65 struct kset *kset;
 
66 struct kobj_type *ktype;
 
67 struct sysfs_dirent *sd;
 
68 unsigned int state_initialized:1;
 
69 unsigned int state_in_sysfs:1;
 
70 unsigned int state_add_uevent_sent:1;
 
71 unsigned int state_remove_uevent_sent:1;
 
72 };

到底了,为啥到底了。去看看linux-source-2.6.26/Document/kobject.txt就知道为啥到底了。

那么kobject到底是个啥?

kobject就是组成Linux的设备模型的基本数据结构。kobject的任务有:

(1)对内核对象的计数,对应数据结构就是struct kref

(2)sysfs表述

(3)数据结构关联

(4)热插拔处理

对usb_driver一层一层的拨开,最后走到了kobject。在内核设计中也用到了面向对象的思想,kobject就可以当作基类,其他的类都是从kobject继承的,由于C语言不能像C++那样继承,所以就一次又一次的封装。

我现在搞清楚了各个struct之间的关系:

kobject—>driver_private—>device_driver—>usbdrv_wrap—>usb_driver

总结他们之间的关系如下:

kobject是Linux设备模型的基本数据结构,它被作为“基类”,其他“子类”都是“继承”了kobject。在我分析的这个例子中,driver_private就是一个“子类”,它直接“继承”了kobject。事实上,老版本的内核(2.6.10)直接把kobject放在device_driver中,新版本的内核则是用driver_private来存放kobject,然后再把driver_private封装在device_driver中。device_driver中除了包含driver_private,还有很多函数指针,也就是驱动程序需要提供的服务。接下来,usbdrv_wrap再次封装了device_driver,这次封装很简单,没有增加过多额外的字段。最后usb_driver来封装usbdrv_wrap,usb_driver中也有很多的函数指针。

这些结构体的各个字段,具体作用是什么?尤其是最接近“基类”的那些“子类”的以k开头的字段,都用来实现什么功能?

驱动程序提供的服务又是什么样子,以及USB驱动程序在总线上的挂牌过程,这些都需要弄明白,下一篇笔记看看能不能弄清楚。