在第五节我们说过会专门分析函数usb_device_match,以体现模型的重要性。同时,我们还是要守信用的。
再贴一遍代码,看代码就要不厌其烦:
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
if (is_usb_device(dev)) {
/* interface drivers never match devices */
if (!is_usb_device_driver(drv))
return 0;usb_device_driver
/* TODO: Add real matching code */
return 1;
usb_device
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* device drivers never match interfaces */
if (is_usb_device_driver(drv))
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id(intf, usb_drv->id_table);
if (id)
return 1;
id = usb_match_dynamic_id(intf, usb_drv);
if (id)
return 1;
}
return 0;
}
前面说过,总线上挂着两条链表,一条是设备链表,一条是驱动链表,经过漫长的岁月里的煎熬,终于通过usb_device_match这位大媒人的牵引下一个个的匹配成功了,当然也会有失败哦,缘分天注定嘛。
USB的世界里,设备和驱动对于我们来说是不可言传的玄机,对于它们来说只是usb_device_match函数的两端。usb_device_match函数为它们指明哪个才是它们命中注定的缘。第一次遇到这个函数的时候,就说了这里有两条路,一条给USB设备走,一条给USB接口走。
is_usb_device函数相当于是一个把门的,在进入关卡前需要安检一样:
static inline int is_usb_device(const struct device *dev)
{
return dev->type == &usb_device_type;
}
is_usb_device函数里的usb_device_type定义如下:
struct device_type usb_device_type = {
.name = "usb_device",
.release = usb_release_dev,
};
假设现在过来一个设备,经过判断,它要走的是设备这条路,可问题是,这个设备的type字段啥时候被初始化成usb_device_type了,暂且不表,带着疑问上路吧?
is_usb_device_driver函数脸上写着我是用来判断是不是usb device driver的,那咱们就要讨论什么是usb device driver?前面一直都说一个usb接口对应一个usb驱动。对吗?你是不是曾经怀疑过?我可以负责任的告诉你,你记得没错,一个接口就是要对应一个usb驱动,可是我们不能只钻到接口的那个口里边儿,我们应该眼光放的更加开阔些,要知道接口在usb的世界里并不是老大,它上边儿还有配置,还有设备,都比它大。每个接口对应了一个独立的功能,是需要专门的驱动来和它交流,但是接口毕竟整体是作为一个usb设备而存在的,设备还可以有不同的配置,我们还可以为设备指定特定的配置,那谁来做这个事情?接口驱动么?它还不够级别,它的级别只够和接口会谈会谈。这个和整个usb设备进行对等交流的光荣任务就交给了struct usb_device _driver,即usb设备驱动,它和usb的接口驱动struct usb_driver都定义在include/linux/usb.h文件里。现在明白/* interface drivers never match devices */注释的含义了吗????含蓄的我都不想再解释了。
/**
* struct usb_driver - identifies USB interface driver to usbcore
* @name: The driver name should be unique among USB drivers,
* and should normally be the same as the module name.
* @probe: Called to see if the driver is willing to manage a particular
* interface on a device. If it is, probe returns zero and uses
* usb_set_intfdata() to associate driver-specific data with the
* interface. It may also use usb_set_interface() to specify the
* appropriate altsetting. If unwilling to manage the interface,
* retur