本文是基于mini2440开发板Linux版本号是linux-2.6.32.2的学习笔记
注册driver的函数是driver_register,device_driver传参如下:
new_udriver->drvwrap.for_devices = 1;
new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
new_udriver->drvwrap.driver.bus = &usb_bus_type;
new_udriver->drvwrap.driver.probe = usb_probe_device;
new_udriver->drvwrap.driver.remove = usb_unbind_device;
new_udriver->drvwrap.driver.owner = owner;
注册device的函数是device_add,device传参如下:
dev->dev.bus = &usb_bus_type;
dev->dev.type = &usb_device_type;
dev->dev.groups = usb_device_groups;
driver和device的总线都是usb_bus_type,device的设备类型是usb_device_type,driver的probe函数是usb_probe_device。
那么注册设备的时候,会自动遍历总线上的所有驱动,看看哪个驱动能匹配上;
注册驱动的时候,也会遍历总线上的所有设备,看看哪个设备能匹配上;
usb_bus_type的定义如下:
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
};
usb_device_match是他们的匹配函数
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
//如果是USB设备
if (is_usb_device(dev)) {
/* interface drivers never match devices */
//是匹配USB设备的驱动,USB接口的驱动不能匹配
if (!is_usb_device_driver(drv))
return 0;
/* TODO: Add real matching code */
return 1;
} else if (is_usb_interface(dev)) { //如果是USB接口
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* device drivers never match interfaces */
//usb接口在注册driver时将for_devices设置为0,for_devices =1,表示设备驱动,for_devices = 0,表示接口驱动
if (is_usb_device_driver(drv))
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
//匹配id table
id = usb_match_id(intf, usb_drv->id_table);
if (id)
return 1;
//匹配动态id table
id = usb_match_dynamic_id(intf, usb_drv);
if (id)
return 1;
}
return 0;
}
匹配规则是:
usb 设备device和usb 设备driver任意匹配;
usb device和usb 接口driver不能匹配;
usb 接口device和usb设备driver不能匹配;
usb接口device和usb接口driver根据driver的id_table进行匹配;
现在是root hub的usb设备device和usb设备driver进行匹配,所以直接就匹配上了,调用usb_probe_device函数。
static int usb_probe_device(struct device *dev)
{
……
error = udriver->probe(udev);
return error;
}
usb_probe_device函数直接调用usb_device_driver的probe函数。
usb_device_driver只在usb_init函数中调用usb_register_device_driver传进来的。
static int __init usb_init(void)
{
……
retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
}
看一下usb_generic_driver这个全局变量。
struct usb_device_driver usb_generic_driver = {
.name = "usb",
.probe = generic_probe,
.disconnect = generic_disconnect,
#ifdef CONFIG_PM
.suspend = generic_suspend,
.resume = generic_resume,
#endif
.supports_autosuspend = 1,
};
usb_generic_driver的probe函数是generic_probe,所以root hub的usb设备device和usb设备driver进行匹配最终调用的是generic_probe函数。
static int generic_probe(struct usb_device *udev)
{
int err, c;
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
if (usb_device_is_owned(udev))
; /* Don't configure if the device is owned */
else if (udev->authorized == 0)
dev_err(&udev->dev, "Device is not authorized for usage\n");
else {
//选择一个合适的设置
c = usb_choose_configuration(udev);
if (c >= 0) {
//设置
err = usb_set_configuration(udev, c);
if (err) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
return 0;
}
主要是为root hub选择一个合适的配置,然后配置root hub。但是root hub只有一个配置,其实也没得选。
看一下usb_choose_configuration函数。
int usb_choose_configuration(struct usb_device *udev)
{
……
/* Rule out configs that draw too much bus current */
if (c->desc.bMaxPower * 2 > udev->bus_mA) {
insufficient_power++;
continue;
}
/* From the remaining configs, choose the first one whose
* first interface is for a non-vendor-specific class.
* Reason: Linux is more likely to have a class driver
* than a vendor-specific driver. */
else if (udev->descriptor.bDeviceClass !=
USB_CLASS_VENDOR_SPEC &&
(!desc || desc->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC)) {
best = c;
break;
}
/* If all the remaining configs are vendor-specific,
* choose the first one. */
else if (!best)
best = c;
}
选择配置的选择就是耗电量太大的不选,厂商特殊定义的DeviceClass不选,都是厂商特殊定义的DeviceClass,选择第一个。
然后看一下配置函数。
int usb_set_configuration(struct usb_device *dev, int configuration)
{
int i, ret;
struct usb_host_config *cp = NULL;
struct usb_interface **new_interfaces = NULL;
int n, nintf;
//configuration是前边儿choose_configuration()那里返回回来的
//当configuration为-1也就是没有发现满意的配置时,设备不能进入Configured,
//所以要把configuration的值改为0,以便满足SET_CONFIGURATION请求的要求
if (dev->authorized == 0 || configuration == -1)
configuration = 0;
else {
//从设备struct usb_device结构体的config数组里将相应配置的描述信息,也就是struct usb_host_config结构体给取出来
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
if (dev->config[i].desc.bConfigurationValue ==
configuration) {
cp = &dev->config[i];
break;
}
}
}
if ((!cp && configuration != 0))
return -EINVAL;
/* The USB spec says configuration 0 means unconfigured.
* But if a device includes a configuration numbered 0,
* we will accept it as a correctly configured state.
* Use -1 if you really want to unconfigure the device.
*/
if (cp && configuration == 0)
dev_warn(&dev->dev, "config 0 descriptor??\n");
/* Allocate memory for new interfaces before doing anything else,
* so that if we run out then nothing will have changed. */
n = nintf = 0;
if (cp) {
nintf = cp->desc.bNumInterfaces;
//申请指针数组的内存
new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
GFP_KERNEL);
if (!new_interfaces) {
dev_err(&dev->dev, "Out of memory\n");
return -ENOMEM;
}
//申请每一项new_interfaces[n]的内存
for (; n < nintf; ++n) {
new_interfaces[n] = kzalloc(
sizeof(struct usb_interface),
GFP_KERNEL);
if (!new_interfaces[n]) {
dev_err(&dev->dev, "Out of memory\n");
ret = -ENOMEM;
free_interfaces:
while (--n >= 0)
kfree(new_interfaces[n]);
kfree(new_interfaces);
return ret;
}
}
i = dev->bus_mA - cp->desc.bMaxPower * 2;
if (i < 0)
dev_warn(&dev->dev, "new config #%d exceeds power "
"limit by %dmA\n",
configuration, -i);
}
/* Wake up the device so we can send it the Set-Config request */
ret = usb_autoresume_device(dev);
if (ret)
goto free_interfaces;
/* Make sure we have bandwidth (and available HCD resources) for this
* configuration. Remove endpoints from the schedule if we're dropping
* this configuration to set configuration 0. After this point, the
* host controller will not allow submissions to dropped endpoints. If
* this call fails, the device state is unchanged.
*/
if (cp)
ret = usb_hcd_check_bandwidth(dev, cp, NULL);
else
ret = usb_hcd_check_bandwidth(dev, NULL, NULL);
if (ret < 0) {
usb_autosuspend_device(dev);
goto free_interfaces;
}
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
//不disable ep0
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device(dev, 1); /* Skip ep0 */
/* Get rid of pending async Set-Config requests for this device */
cancel_async_set_config(dev);
//发送命令,设置configuration
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT);
if (ret < 0) {
/* All the old state is gone, so what else can we do?
* The device is probably useless now anyway.
*/
cp = NULL;
}
//将激活的那个配置的地址赋给actconfig
dev->actconfig = cp;
//如果cp为空,重新设置设备的状态为Address,并将之前
//准备的那些struct usb_interface结构体和new_interfaces释放掉,然后返回
if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
usb_hcd_check_bandwidth(dev, NULL, NULL);
usb_autosuspend_device(dev);
goto free_interfaces;
}
//设置设备的状态为configured
usb_set_device_state(dev, USB_STATE_CONFIGURED);
/* Initialize the new interface structures and the
* hc/hcd/usbcore interface/endpoint state.
*/
for (i = 0; i < nintf; ++i) {
struct usb_interface_cache *intfc;
struct usb_interface *intf;
struct usb_host_interface *alt;
cp->interface[i] = intf = new_interfaces[i];
intfc = cp->intf_cache[i];
intf->altsetting = intfc->altsetting;
intf->num_altsetting = intfc->num_altsetting;
intf->intf_assoc = find_iad(dev, cp, i);
kref_get(&intfc->ref);
//获得这个接口的0号设置,接口的默认设置总是0号设置
alt = usb_altnum_to_altsetting(intf, 0);
/* No altsetting 0? We'll assume the first altsetting.
* We could use a GetInterface call, but if a device is
* so non-compliant that it doesn't have altsetting 0
* then I wouldn't trust its reply anyway.
*/
//拿altsetting数组里的第一项来充数
if (!alt)
alt = &intf->altsetting[0];
//指定刚刚拿到的设置为当前要使用的设置
intf->cur_altsetting = alt;
//轮询前面获得的那个接口设置使用到的每个端点,将它们统统enable
usb_enable_interface(dev, intf, true);
intf->dev.parent = &dev->dev;
intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
intf->dev.groups = usb_interface_groups;
intf->dev.dma_mask = dev->dev.dma_mask;
INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
device_initialize(&intf->dev);
mark_quiesced(intf);
dev_set_name(&intf->dev, "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration, alt->desc.bInterfaceNumber);
}
kfree(new_interfaces);
if (cp->string == NULL &&
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
/* Now that all the interfaces are set up, register them
* to trigger binding of drivers to interfaces. probe()
* routines may install different altsettings and may
* claim() any interfaces not yet bound. Many class drivers
* need that: CDC, audio, video, etc.
*/
//将前面那个for循环准备好的每个接口送给设备模型
for (i = 0; i < nintf; ++i) {
struct usb_interface *intf = cp->interface[i];
dev_dbg(&dev->dev,
"adding %s (config #%d, interface %d)\n",
dev_name(&intf->dev), configuration,
intf->cur_altsetting->desc.bInterfaceNumber);
ret = device_add(&intf->dev);
if (ret != 0) {
dev_err(&dev->dev, "device_add(%s) --> %d\n",
dev_name(&intf->dev), ret);
continue;
}
create_intf_ep_devs(intf);
}
usb_autosuspend_device(dev);
return 0;
}
代码非常长,主要做的事情就是:
参数检查,申请内存;
发送命令,设置configuration编号,因为我们上一步选择了一个合适的配置;
设置设备的状态为configured;
将解析阶段usb_host_config.intf_cache中保存的数据保存在usb_host_config.interface,usb_host_config.intf_cache的数据只在设备为配置状态之前有效,设备处于配置状态后,使用usb_host_config.interface里面的数据;
根据configured可以知道有多少个接口,对每个接口进行初始化,初始化dev设备,初始化它的设置,指定每个接口当前活跃的设置为0号设置;
intf->dev.parent = &dev->dev;
intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
intf->dev.groups = usb_interface_groups;
将每个接口注册成usb接口设备;
我们的root hub只有一种配置,一种接口,一种设置和一个端口,上面的usb接口设备的总线是usb_bus_type,设备类型是usb_if_device_type,这个后面就会用到。
文章参考:https://blog.youkuaiyun.com/fudan_abc/article/category/325189