USB从入门到精通-2-Linux那些事儿之USB学习与扩展

标签: USB协议 UKey分析


资源来自《Linux那些事儿之USB》,本文主要是读书笔记,附加一些自己的分析和相关知识点说明
内核代码版本2.6.24

目录

4. 设备生命线

4.1. Hub监听处理

插到Hub到拔出。当USB设备连接到Hub某端口上时,Hub检测到有设备连接后,会分配一个struct usb_device结构并初始化,调用设备模型提供的接口将设备添加到USB总线的设备列表中,然后USB总线会遍历驱动列表中的每个驱动,调用自己的match函数看是否和设备或接口匹配。
Hub检测过程如下:

Created with Raphaël 2.1.2 usb_init hub_thread hub_events hub_port_connect_change 设备新增相关操作

其中hub_port_connect_change关键代码如下:

    for (i = 0; i < SET_CONFIG_TRIES; i++) {
        struct usb_device *udev;

        /* reallocate for each attempt, since references
         * to the previous one can escape in various ways
         */
        udev = usb_alloc_dev(hdev, hdev->bus, port1);
        //Hub检测到端口有设备连接后,会调用core的usb_alloc_dev函数
        //为struct usb_device结构的对象申请内容,详见4.1.1
        if (!udev) {
            dev_err (hub_dev,
                "couldn't allocate port %d usb_device\n",
                port1);
            goto done;
        }

        usb_set_device_state(udev, USB_STATE_POWERED);
        udev->speed = USB_SPEED_UNKNOWN;
        udev->bus_mA = hub->mA_per_port;
        udev->level = hdev->level + 1;
        //完成struct usb_device结构体创建后,hub会进行后续初始化工作
        //将设备状态设置为powered(加电状态)
        //将speed暂时设置为USB_SPEED_UNKNOWN,核心就是成员属性设置
        //设备level设置为Hub level+1
        //为设备能够从Hub那里获得的电流赋值,为了保证通信  
        /* set the address */
        choose_address(udev);
        if (udev->devnum <= 0) {
            status = -ENOTCONN; /* Don't retry */
            goto loop;
        }
        //Hub会为设备在总线上选择独一无二的地址,设置usb_device->devnum

        /* reset and get descriptor */
        status = hub_port_init(hub, udev, port1, i);
        //复位、设置地址、并获得设备描述符,详见下文
        if (status < 0)
            goto loop;

        /* consecutive bus-powered hubs aren't reliable; they can
         * violate the voltage drop budget.  if the new child has
         * a "powered" LED, users should notice we didn't enable it
         * (without reading syslog), even without per-port LEDs
         * on the parent.
         */
        if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
                && udev->bus_mA <= 100) {
            //如果设备类型是USB_CLASS_HUB进行的特殊处理,暂不关心
            u16 devstat;

            status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
                    &devstat);
            if (status < 2) {
                dev_dbg(&udev->dev, "get status %d ?\n", status);
                goto loop_disable;
            }
            le16_to_cpus(&devstat);
            if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
                dev_err(&udev->dev,
                    "can't connect bus-powered hub "
                    "to this port\n");
                if (hub->has_indicators) {
                    hub->indicator[port1-1] =
                        INDICATOR_AMBER_BLINK;
                    schedule_delayed_work (&hub->leds, 0);
                }
                status = -ENOTCONN; /* Don't retry */
                goto loop_disable;
            }
        }

        /* check for devices running slower than they could */
        if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200
                && udev->speed == USB_SPEED_FULL
                && highspeed_hubs != 0)
            check_highspeed (hub, udev, port1);

        /* Store the parent's children[] pointer.  At this point
         * udev becomes globally accessible, although presumably
         * no one will look at it until hdev is unlocked.
         */
        status = 0;

        /* We mustn't add new devices if the parent hub has
         * been disconnected; we would race with the
         * recursively_mark_NOTATTACHED() routine.
         */
        spin_lock_irq(&device_state_lock);
        if (hdev->state == USB_STATE_NOTATTACHED)
            status = -ENOTCONN;
        else
            hdev->children[port1-1] = udev;
        spin_unlock_irq(&device_state_lock);

        /* Run it through the hoops (find a driver, etc) */
        if (!status) {
            status = usb_new_device(udev);
            //核心调用,初始化设备配置,详见4.1.4
            if (status) {
                spin_lock_irq(&device_state_lock);
                hdev->children[port1-1] = NULL;
                spin_unlock_irq(&device_state_lock);
            }
        }

        if (status)
            goto loop_disable;

        status = hub_power_remaining(hub);
        if (status)
            dev_dbg(hub_dev, "%dmA power budget left\n", status);

        return;

loop_disable:
        hub_port_disable(hub, port1, 1);
loop:
        ep0_reinit(udev);
        release_address(udev);
        usb_put_dev(udev);
        if ((status == -ENOTCONN) || (status == -ENOTSUPP))
            break;
    }

设备要想从Powered状态发展到下一个Default状态,必须收到一个复位信号,并成功复位。Hub会复位设备,成功后,设备进入Default状态。

复位进入Default状态后,Hub也会获得设备真正的速度,依据速度,能过知道端口0一次能够处理的最大数据长度。

下面Hub使用Core中定义的usb_control_msg函数给设备发送SET_ADDRESS请求,设备就进入Address状态了,设备的address就是上表中的Devnum

4.1.1 usb_alloc_dev-USB设备对象创建

下面来分析一下usb_alloc_dev函数的实现

struct usb_device *
usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
//USB设备的构造函数,parent是设备连接的hub,bus是设备连接的总线,port1是设备连接在Hub上的端口
{
    struct usb_device *dev;
    struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
    unsigned root_hub = 0;

    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    //申请struct usb_device空间,kzalloc=kmalloc+memset
    if (!dev)
        return NULL;

    if (!usb_get_hcd(bus_to_hcd(bus))) {
    //hcd,主机控制器驱动相关的函数,主机控制器对应一条USB总线,用struct usb_hcd结构表示
    //一条总线用struct usb_bus结构表示
    //函数bus_to_hcd,获得总线对应的主机控制器驱动,也就是struct usb_hcd结构对象
    //函数usb_get_hcd将得到的usb_hcd结构对象的引用计数加1,,因为总线上多了一个设备
        kfree(dev);
        return NULL;
    }

    device_initialize(&dev->dev);
    //设备模型的函数,目的是将struct usb_device结构中嵌入的struct device结构体初始化掉
    dev->dev.bus = &usb_bus_type;
    //设置总线类型为usb_bus_type
    dev->dev.type = &usb_device_type;
    //设置设备类型为usb_device_type
    /*除了总线类型,还有设备类型,如下
    struct device_type usb_device_type = {
        .name =     "usb_device",
        .release =  usb_release_dev,
        .uevent =   usb_dev_uevent,
    };
    */
    dev->dev.dma_mask = bus->controller->dma_mask;
    //DMA传输设备,是否支持DMA要看主机控制器的dma_mask
    set_dev_node(&dev->dev, dev_to_node(bus->controller));
    //设置内存节点,numa,uma表示一致内存访问,uniform memory access
    dev->state = USB_STATE_ATTACHED;
    //将USB设备的状态设置为ATTACHED,表示已经连接到USB接口上
    atomic_set(&dev->urbnum, 0);

    INIT_LIST_HEAD(&dev->ep0.urb_list);
    //初始化ep0端点的urb_list
    dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
    dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
    //初始化ep0的描述符长度和描述符类型
    /* ep0 maxpacket comes later, from device descriptor */
    usb_enable_endpoint(dev, &dev->ep0);
    //设置usb_device,ep_out[0]和ep_in[0]
    dev->can_submit = 1;

    /* Save readable and stable topology id, distinguishing devices
     * by location for diagnostics, tools, driver model, etc.  The
     * string is a path along hub ports, from the root.  Each device's
     * dev->devpath will be stable until USB is re-cabled, and hubs
     * are often labeled with these port numbers.  The bus_id isn't
     * as stable:  bus->busnum changes easily from modprobe order,
     * cardbus or pci hotplugging, and so on.
     */
    if (unlikely(!parent)) {
        //告诉编译器条件x发生的可能性不大,这个条件块里的语句目标码可以放在较远位置,保证经常执行的目标更紧凑
        //这里parent为空,表示设备直接连载root hub上
        //内核觉得USB设置直接连到root hub上可能性很小
        dev->devpath[0] = '0';

        dev->dev.parent = bus->controller;
        sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum);
        root_hub = 1;
        //如果是连接到root hub,那么需要设置的usb_device的属性
        //usb_device->devpath="0"
        //usb_device->dev(struct device类型).parent(struct device类型)=主机控制器
        //usb_device->dev(struct device类型).bus_id[]="usb1"或者usb2\3\4这样的字符串
    } else {
        /* match any labeling on the hubs; it's one-based */
        if (parent->devpath[0] == '0')
            snprintf(dev->devpath, sizeof dev->devpath,
                "%d", port1);
        else
            snprintf(dev->devpath, sizeof dev->devpath,
                "%s.%d", parent->devpath, port1);

        dev->dev.parent = &parent->dev;
        sprintf(&dev->dev.bus_id[0], "%d-%s",
            bus->busnum, dev->devpath);
        //如果不是连接到root hub,那么需要设置的usb_device的属性
        //如果所在hub在Root Hub上,那么usb_device->devpath=端口号
        //否则usb_device->devpath=所在Hub的devpath基础上加一个.再加端口号
        //usb_device->dev(struct device类型).parent(struct device类型)=parent->dev
        //usb_device->dev(struct device类型).bus_id[]=(bus->busnum)-(dev->devpath)
        /* hub driver sets up TT records */
    }

    dev->portnum = port1;
    dev->bus = bus;
    dev->parent = parent;
    INIT_LIST_HEAD(&dev->filelist);
    //初始化一个链表

    //下面是电源管理相关
#ifdef  CONFIG_PM
    mutex_init(&dev->pm_mutex);
    INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
    dev->autosuspend_delay = usb_autosuspend_delay * HZ;
#endif
    if (root_hub)   /* Root hub always ok [and always wired] */
        dev->authorized = 1;
    else {
        dev->authorized = usb_hcd->authorized_default;
        dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
    }
    return dev;
}
4.1.2. hub_port_init-设备复位、设备Address、设备描述符获取

代码如下:

static int
hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        int retry_counter)
{
    static DEFINE_MUTEX(usb_address0_mutex);

    struct usb_device   *hdev = hub->hdev;
    int         i, j, retval;
    unsigned        delay = HUB_SHORT_RESET_TIME;
    enum usb_device_speed   oldspeed = udev->speed;
    char            *speed, *type;
    int         devnum = udev->devnum;

    /* root hub ports have a slightly longer reset period
     * (from USB 2.0 spec, section 7.1.7.5)
     */
    if (!hdev->parent) {
        delay = HUB_ROOT_RESET_TIME;
        if (port1 == hdev->bus->otg_port)
            hdev->bus->b_hnp_enable = 0;
    }

    /* Some low speed devices have problems with the quick delay, so */
    /*  be a bit pessimistic with those devices. RHbug #23670 */
    if (oldspeed == USB_SPEED_LOW)
        delay = HUB_LONG_RESET_TIME;

    mutex_lock(&usb_address0_mutex);

    /* Reset the device; full speed may morph to high speed */
    retval = hub_port_reset(hub, port1, udev, delay);
    //设备复位,得到真正的设备速度(udev->speed),详见下文
    if (retval < 0)     /* error or disconnect */
        goto fail;
                /* success, speed is known */
    retval = -ENODEV;

    if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) {
        dev_dbg(&udev->dev, "device reset changed speed!\n");
        goto fail;
    }
    oldspeed = udev->speed;

    /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
     * it's fixed size except for full speed devices.
     * For Wireless USB devices, ep0 max packet is always 512 (tho
     * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
     */
     //下面依据设备驱动,设置端点0的一次能够处理的最大长度
    switch (udev->speed) {
    case USB_SPEED_VARIABLE:    /* fixed at 512 */
        udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512);
        break;
    case USB_SPEED_HIGH:        /* fixed at 64 */
        udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
        break;
    case USB_SPEED_FULL:        /* 8, 16, 32, or 64 */
        /* to determine the ep0 maxpacket size, try to read
         * the device descriptor to get bMaxPacketSize0 and
         * then correct our initial guess.
         */
        udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
        break;
    case USB_SPEED_LOW:     /* fixed at 8 */
        udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8);
        break;
    default:
        goto fail;
    }

     //下面是printk输出
    type = "";
    switch (udev->speed) {
    case USB_SPEED_LOW: speed = "low";  break;
    case USB_SPEED_FULL:    speed = "full"; break;
    case USB_SPEED_HIGH:    speed = "high"; break;
    case USB_SPEED_VARIABLE:
                speed = "variable";
                type = "Wireless ";
                break;
    default:        speed = "?";    break;
    }
    dev_info (&udev->dev,
          "%s %s speed %sUSB device using %s and address %d\n",
          (udev->config) ? "reset" : "new", speed, type,
          udev->bus->controller->driver->name, devnum);
    //下面是TT:transaction translator,负责高速和低速/全速的数据转换
    /* Set up TT records, if needed  */
    if (hdev->tt) {
        udev->tt = hdev->tt;
        udev->ttport = hdev->ttport;
    } else if (udev->speed != USB_SPEED_HIGH
            && hdev->speed == USB_SPEED_HIGH) {
        udev->tt = &hub->tt;
        udev->ttport = port1;
    }

    /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
     * Because device hardware and firmware is sometimes buggy in
     * this area, and this is how Linux has done it for ages.
     * Change it cautiously.
     *
     * NOTE:  If USE_NEW_SCHEME() is true we will start by issuing
     * a 64-byte GET_DESCRIPTOR request.  This is what Windows does,
     * so it may help with some non-standards-compliant devices.
     * Otherwise we start with SET_ADDRESS and then try to read the
     * first 8 bytes of the device descriptor to get the ep0 maxpacket
     * value.
     */
     //从字面意思来说是获取描述符
    for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
        if (USE_NEW_SCHEME(retry_counter)) {  //暂时不考虑这个NEW——SCHEME
            struct usb_device_descriptor *buf;
            int r = 0;

#define GET_DESCRIPTOR_BUFSIZE  64
            buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
            if (!buf) {
                retval = -ENOMEM;
                continue;
            }

            /* Retry on all errors; some devices are flakey.
             * 255 is for WUSB devices, we actually need to use
             * 512 (WUSB1.0[4.8.1]).
             */
            for (j = 0; j < 3; ++j) {
                buf->bMaxPacketSize0 = 0;
                r = usb_control_msg(udev, usb_rcvaddr0pipe(),
                    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                    USB_DT_DEVICE << 8, 0,
                    buf, GET_DESCRIPTOR_BUFSIZE,
                    USB_CTRL_GET_TIMEOUT);
                switch (buf->bMaxPacketSize0) {
                case 8: case 16: case 32: case 64: case 255:
                    if (buf->bDescriptorType ==
                            USB_DT_DEVICE) {
                        r = 0;
                        break;
                    }
                    /* FALL THROUGH */
                default:
                    if (r == 0)
                        r = -EPROTO;
                    break;
                }
                if (r == 0)
                    break;
            }
            udev->descriptor.bMaxPacketSize0 =
                    buf->bMaxPacketSize0;
            kfree(buf);

            retval = hub_port_reset(hub, port1, udev, delay);
            if (retval < 0)     /* error or disconnect */
                goto fail;
            if (oldspeed != udev->speed) {
                dev_dbg(&udev->dev,
                    "device reset changed speed!\n");
                retval = -ENODEV;
                goto fail;
            }
            if (r) {
                dev_err(&udev->dev, "device descriptor "
                        "read/%s, error %d\n",
                        "64", r);
                retval = -EMSGSIZE;
                continue;
            }
#undef GET_DESCRIPTOR_BUFSIZE
        }

        for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
            retval = hub_set_address(udev, devnum);
            //设置usb_device的地址,将当前devnum成员值告诉设备
            //就是调用usb_control_msg,展开调用如下:
            //usb_control_msg(udev, usb_sndaddr0pipe(),
        USB_REQ_SET_ADDRESS, 0, devnum, 0,
        NULL, 0, USB_CTRL_SET_TIMEOUT);
            if (retval >= 0)
                break;
            msleep(200);
        }
        if (retval < 0) {
            dev_err(&udev->dev,
                "device not accepting address %d, error %d\n",
                devnum, retval);
            goto fail;
        }

        /* cope with hardware quirkiness:
         *  - let SET_ADDRESS settle, some device hardware wants it
         *  - read ep0 maxpacket even for high and low speed,
         */
        msleep(10);
        if (USE_NEW_SCHEME(retry_counter))
            break;

        retval = usb_get_device_descriptor(udev, 8);
        //核心,获取设备描述符,此时size为0,猜测应该没有真正获取,真正的获取应该在下面
        //本函数调用usb_get_descriptor,后者调用usb_control_msg(USB_REG_GET_DESCRIPTOR)
        //然后将获取到的描述符,赋值给usb_device->descriptor(usb_device_descriptor类型)
        if (retval < 8) {
            dev_err(&udev->dev, "device descriptor "
                    "read/%s, error %d\n",
                    "8", retval);
            if (retval >= 0)
                retval = -EMSGSIZE;
        } else {
            retval = 0;
            break;
        }
    }
    if (retval)
        goto fail;

    i = udev->descriptor.bMaxPacketSize0 == 0xff?
        512 : udev->descriptor.bMaxPacketSize0;
    if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
        if (udev->speed != USB_SPEED_FULL ||
                !(i == 8 || i == 16 || i == 32 || i == 64)) {
            dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
            retval = -EMSGSIZE;
            goto fail;
        }
        dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
        udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
        ep0_reinit(udev);
    }

    retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
    //核心,获取设备描述符,此时size为USB_DT_DEVICE_SIZE,应该进行了真正获取和赋值
        //本函数调用usb_get_descriptor,后者调用usb_control_msg(USB_REG_GET_DESCRIPTOR)
        //然后将获取到的描述符,赋值给usb_device->descriptor(usb_device_descriptor类型)
    if (retval < (signed)sizeof(udev->descriptor)) {
        dev_err(&udev->dev, "device descriptor read/%s, error %d\n",
            "all", retval);
        if (retval >= 0)
            retval = -ENOMSG;
        goto fail;
    }

    retval = 0;

fail:
    if (retval) {
        hub_port_disable(hub, port1, 0);
        udev->devnum = devnum;  /* for disconnect processing */
    }
    mutex_unlock(&usb_address0_mutex);
    return retval;
}

其中hub_port_reset实现如下:

static int hub_port_reset(struct usb_hub *hub, int port1,
                struct usb_device *udev, unsigned int delay)
{
    int i, status;

    /* Block EHCI CF initialization during the port reset.
     * Some companion controllers don't like it when they mix.
     */
    down_read(&ehci_cf_port_reset_rwsem);

    /* Reset the port */
    for (i = 0; i < PORT_RESET_TRIES; i++) {
        status = set_port_feature(hub->hdev,
                port1, USB_PORT_FEAT_RESET);
                //核心调用,调用usb_control_msg,展开如下:
                //usb_control_msg(hub->hdev, usb_sndctrlpipe(hub->hdev, 0),
        USB_REQ_SET_FEATURE, USB_RT_PORT, USB_PORT_FEAT_RESET, port1,
        NULL, 0, 1000);
                //usb_control_msg详见4.1.3分析
        if (status)
            dev_err(hub->intfdev,
                    "cannot reset port %d (err = %d)\n",
                    port1, status);
        else {
            status = hub_port_wait_reset(hub, port1, udev, delay);
            //等待reset完成,调用hub_port_status获取端口状态,后者调用get_port_status
            //最终调用usb_control_msg来完成功能
            //依据返回的端口状态,设置udev->speed
            if (status && status != -ENOTCONN)
                dev_dbg(hub->intfdev,
                        "port_wait_reset: err = %d\n",
                        status);
        }

        /* return on disconnect or reset */
        switch (status) {
        case 0:
            /* TRSTRCY = 10 ms; plus some extra */
            msleep(10 + 40);
            udev->devnum = 0;   /* Device now at address 0 */
            //设备目前位于地址0
            /* FALL THROUGH */
        case -ENOTCONN:
        case -ENODEV:
            clear_port_feature(hub->hdev,
                port1, USB_PORT_FEAT_C_RESET);
            /* FIXME need disconnect() for NOTATTACHED device */
            usb_set_device_state(udev, status
                    ? USB_STATE_NOTATTACHED
                    : USB_STATE_DEFAULT);
            //设置设备状态:正常情况下为USB_STATE_DEFAULT
            goto done;
        }

        dev_dbg (hub->intfdev,
            "port %d not enabled, trying reset again...\n",
            port1);
        delay = HUB_LONG_RESET_TIME;
    }

    dev_err (hub->intfdev,
        "Cannot enable port %i.  Maybe the USB cable is bad?\n",
        port1);

 done:
    up_read(&ehci_cf_port_reset_rwsem);
    return status;
}
4.1.3. usb_control_msg发送urb(端点管道)-TODO

usb_control_msg构建URB发送给设备,drivers/usb/core/message.c,接口定义如下:

int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
             __u16 value, __u16 index, void *data, __u16 size, int timeout)

这里暂时不展开分析,只说明一下管道,管道有两端,一端是主机上的缓冲区,一端是设备上的断点,端点有四种类型,每种都有in和out两个方向。确定一条管道需要知道管道两端的地址、方向和类型,主机端是确定的,需要确定的是另一端的设备地址和端点地址。
管道bit7表示方向,bit8-bit14表示设备地址(7位),bit15-bit18表示端点号(16位),bit30-bit31表示管道类型,创建管道的宏定义如下:
include/linux/usb.h

//bit30-bit31:管道类型
#define PIPE_ISOCHRONOUS        0
#define PIPE_INTERRUPT          1
#define PIPE_CONTROL            2
#define PIPE_BULK           3

//bit8-bit14:设备地址,bit15-bit18:端点号
static inline unsigned int __create_pipe(struct usb_device *dev,
        unsigned int endpoint)
{
    return (dev->devnum << 8) | (endpoint << 15);
}

//bit7:方向
#define USB_DIR_OUT         0       /* to device */
#define USB_DIR_IN          0x80        /* to host */

/* Create various pipes... */
#define usb_sndctrlpipe(dev,endpoint)   \
    ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
#define usb_rcvctrlpipe(dev,endpoint)   \
    ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#define usb_sndisocpipe(dev,endpoint)   \
    ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
#define usb_rcvisocpipe(dev,endpoint)   \
    ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#define usb_sndbulkpipe(dev,endpoint)   \
    ((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
#define usb_rcvbulkpipe(dev,endpoint)   \
    ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#define usb_sndintpipe(dev,endpoint)    \
    ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
#define usb_rcvintpipe(dev,endpoint)    \
    ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
4.1.4. usb_new_device-配置设备、设备注册、驱动匹配
/**
 * usb_new_device - perform initial device setup (usbcore-internal)
 * @udev: newly addressed device (in ADDRESS state)
 *
 * This is called with devices which have been enumerated, but not yet
 * configured.  The device descriptor is available, but not descriptors
 * for any device configuration.  The caller must have locked either
 * the parent hub (if udev is a normal device) or else the
 * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
 * udev has already been installed, but udev is not yet visible through
 * sysfs or other filesystem code.
 *
 * It will return if the device is configured properly or not.  Zero if
 * the interface was registered with the driver core; else a negative
 * errno value.
 *
 * This call is synchronous, and may not be used in an interrupt context.
 *
 * Only the hub driver or root-hub registrar should ever call this.
 */
int usb_new_device(struct usb_device *udev)
{
    int err;

    usb_detect_quirks(udev);        /* Determine quirks */
    //预定义了一个usb_device_id数组,按照设备描述符信息进行匹配
    //本质是一个黑名单,匹配成功会进行输出提示
    err = usb_configure_device(udev);   /* detect & probe dev/intfs */
    //核心调用,配置设备,detect & probe 设备或接口,详见下文
    if (err < 0)
        goto fail;
    /* export the usbdev device-node for libusb */
    udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
            (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
    //usb_device->dev(struct device类型).devt(dev_t类型)dev_t赋值
    //主设备号是USB_DEVICE_MAJOR,按照前面的描述,说的是usbfs
    //次设备号是(udev->bus->busnum-1) * 128) + (udev->devnum-1)
    /* Increment the parent's count of unsuspended children */
    if (udev->parent)
        usb_autoresume_device(udev->parent);

    /* Register the device.  The device driver is responsible
     * for adding the device files to sysfs and for configuring
     * the device.
     */
    err = device_add(&udev->dev);
    //注册设备,将设备添加到设备树中,详见下文
    if (err) {
        dev_err(&udev->dev, "can't device_add, error %d\n", err);
        goto fail;
    }

    /* Tell the world! */
    dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
        "SerialNumber=%d\n",
        udev->descriptor.iManufacturer,
        udev->descriptor.iProduct,
        udev->descriptor.iSerialNumber);
    show_string(udev, "Product", udev->product);
    show_string(udev, "Manufacturer", udev->manufacturer);
    show_string(udev, "SerialNumber", udev->serial);
    return err;

fail:
    usb_set_device_state(udev, USB_STATE_NOTATTACHED);
    return err;
}

quirk黑名单如下所示

static const struct usb_device_id usb_quirk_list[] = {
    /* CBM - Flash disk */
    { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
    /* HP 5300/5370C scanner */
    { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },

    /* INTEL VALUE SSD */
    { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },

    /* M-Systems Flash Disk Pioneers */
    { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },

    /* Philips PSC805 audio device */
    { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },

    /* SKYMEDI USB_DRIVE */
    { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },

    { }  /* terminating entry must be last */
};

void usb_detect_quirks(struct usb_device *udev)
{
    const struct usb_device_id *id = usb_quirk_list;

    id = find_id(udev);
    //会调用usb_match_device,按照match_flags进行匹配
    if (id)
        udev->quirks = (u32)(id->driver_info);
    if (udev->quirks)
        dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
                udev->quirks);
    //如果存在,就进行调试输出,USB支持该设备有问题

    /* By default, disable autosuspend for all non-hubs */
#ifdef  CONFIG_USB_SUSPEND
    if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
        udev->autosuspend_disabled = 1;
#endif
}
4.1.4.1 usb_configure_device

usb_configure_device函数实现如下:

static int usb_configure_device(struct usb_device *udev)
{
    int err;

    if (udev->config == NULL) {
        err = usb_get_configuration(udev);
        //如果usb_device的配置为空usb_host_config类型,那么首先获取所有配置,详见下文
        if (err < 0) {
            dev_err(&udev->dev, "can't read configurations, error %d\n",
                err);
            goto fail;
        }
    }
    if (udev->wusb == 1 && udev->authorized == 0) {
        udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
        udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
        udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
    }
    else {
        /* read the standard strings and cache them if present */
        udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
        udev->manufacturer = usb_cache_string(udev,
                              udev->descriptor.iManufacturer);
        udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
        //获取字符串描述符的字符串值,usb_device设备描述符中包含了字符串的位置
        //还是通过usb_control_msg来获取字符串描述符的值
    }
    err = usb_configure_device_otg(udev);
fail:
    return err;
}

usb_get_configuration实现如下:

int usb_get_configuration(struct usb_device *dev)
{
    struct device *ddev = &dev->dev;
    int ncfg = dev->descriptor.bNumConfigurations;//设备描述符中包含配置数
    int result = 0;
    unsigned int cfgno, length;
    unsigned char *buffer;
    unsigned char *bigbuffer;
    struct usb_config_descriptor *desc;

    cfgno = 0;
    if (dev->authorized == 0)   /* Not really an error */
        goto out_not_authorized;
    result = -ENOMEM;
    if (ncfg > USB_MAXCONFIG) {
        dev_warn(ddev, "too many configurations: %d, "
            "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
        dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
    }

    if (ncfg < 1) {
        dev_err(ddev, "no configurations\n");
        return -EINVAL;
    }

    //给usb_device->config创建对应数量的结构体struct usb_host_config空间
    length = ncfg * sizeof(struct usb_host_config);
    dev->config = kzalloc(length, GFP_KERNEL);
    if (!dev->config)
        goto err2;

    //给usb_device->rawdescriptors创建对应数量的字符串char *空间
    //这是一个字符指针数组,里面的每一项都指向一个使用GET_DESCRIPTOR请求去获取配置描述符时的结果
    length = ncfg * sizeof(char *);
    dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
    if (!dev->rawdescriptors)
        goto err2;

    //开辟配置描述符空间,长度为9
    buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
    if (!buffer)
        goto err2;
    desc = (struct usb_config_descriptor *)buffer;

    result = 0;
    for (; cfgno < ncfg; cfgno++) {  //按照配置数进行循环
        /* We grab just the first descriptor so we know how long
         * the whole configuration is */
        result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
            buffer, USB_DT_CONFIG_SIZE);
            //调用usb_control_msg(usb_device,usb_rcvctrlpipe(dev,0),USB_REQ_GET_DESCRIPTOR,USB_DIR_IN,USB_DT_CONFIG<<8+cfgno,buffer,USB_DT_CONFIG_SIZE)
            //发送urb,获取配置描述符
            //但是是用一个for 3次循环进行调用的:
                //一些设备厂商生产设备不守规矩,一次请求还一定能成功
                //但是获取不到无法继续,只能多试几次
        if (result < 0) {   //获取失败
            dev_err(ddev, "unable to read config index %d "
                "descriptor/%s: %d\n", cfgno, "start", result);
            dev_err(ddev, "chopping to %d config(s)\n", cfgno);
            dev->descriptor.bNumConfigurations = cfgno;
            break;
        } else if (result < 4) {    //如果小于4,表示数据太少
        //配置描述符中,第三个字节wTotalLength表示嵌套包含的各类描述符的总大小,
            //第四个字节bNuminterfaces表示接口数量,只要获得了前4个字节,就能得到总长度
            dev_err(ddev, "config index %d descriptor too short "
                "(expected %i, got %i)\n", cfgno,
                USB_DT_CONFIG_SIZE, result);
            result = -EINVAL;
            goto err;
        }
        length = max((int) le16_to_cpu(desc->wTotalLength),
            USB_DT_CONFIG_SIZE);

        /* Now that we know the length, get the whole thing */
        bigbuffer = kmalloc(length, GFP_KERNEL);
        if (!bigbuffer) {
            result = -ENOMEM;
            goto err;
        }
        //按照返回的wTotalLength开辟空间,重新调用usb_get_descriptor
            //获取嵌套的各级配置描述符
        result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
            bigbuffer, length);
        if (result < 0) {
            dev_err(ddev, "unable to read config index %d "
                "descriptor/%s\n", cfgno, "all");
            kfree(bigbuffer);
            goto err;
        }
        if (result < length) {
            dev_warn(ddev, "config index %d descriptor too short "
                "(expected %i, got %i)\n", cfgno, length, result);
            length = result;
        }

        dev->rawdescriptors[cfgno] = bigbuffer;
        //赋值给usb_device->rawdescriptors[i]

        result = usb_parse_configuration(&dev->dev, cfgno,
            &dev->config[cfgno], bigbuffer, length);
        //配置信息的解析,就是从前面获取的所有数据中解析出各个描述符,详见下文
        if (result < 0) {
            ++cfgno;
            goto err;
        }
    }
    result = 0;

err:
    kfree(buffer);
out_not_authorized:
    dev->descriptor.bNumConfigurations = cfgno;
err2:
    if (result == -ENOMEM)
        dev_err(ddev, "out of memory\n");
    return result;
}

GET_DESCRIPTOR请求说明如下:
GET_DESCRIPTOR请求

GET_DESCRIPTOR得到的数据并不是杂乱无序的,是有规律的,一般来说,配置描述符后面跟的就是第一个接口的接口描述符,接着就是这个接口里第一个端点的端点描述符,如果有class-和vendor-specific描述符的话,会紧跟在对应的标准描述符后面,不管接口有多少个端点都是按照这个规律顺序排列。总的来说,肯定先是配置描述符,然后是其包含的接口描述符,然后是该接口包含的端点描述符,例如config1+interface1+ep1+ep2+interface2+ep1+ep2+interface3。
usb_parse_configuration函数实现如下:

static int usb_parse_configuration(struct device *ddev, int cfgidx,
    struct usb_host_config *config, unsigned char *buffer, int size)
{
    unsigned char *buffer0 = buffer;
    int cfgno;
    int nintf, nintf_orig;
    int i, j, n;
    struct usb_interface_cache *intfc;
    unsigned char *buffer2;
    int size2;
    struct usb_descriptor_header *header;
    int len, retval;
    u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
    unsigned iad_num = 0;

    memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
    //buffer的前USB_DT_CONFIG_SIZE长度一定是配置描述符,直接拷贝
    if (config->desc.bDescriptorType != USB_DT_CONFIG ||
        config->desc.bLength < USB_DT_CONFIG_SIZE) {
        //里面做一个校验判断
        dev_err(ddev, "invalid descriptor for config index %d: "
            "type = 0x%X, length = %d\n", cfgidx,
            config->desc.bDescriptorType, config->desc.bLength);
        return -EINVAL;
    }
    cfgno = config->desc.bConfigurationValue;
    //指明了将要激活哪个配置
    buffer += config->desc.bLength;
    size -= config->desc.bLength;
    //buffer指针位置和size修正

    nintf = nintf_orig = config->desc.bNumInterfaces;
    //配置数量
    if (nintf > USB_MAXINTERFACES) {
        dev_warn(ddev, "config %d has too many interfaces: %d, "
            "using maximum allowed: %d\n",
            cfgno, nintf, USB_MAXINTERFACES);
        nintf = USB_MAXINTERFACES;
    }

    /* Go through the descriptors, checking their length and counting the
     * number of altsettings for each interface */
    n = 0;
    for ((buffer2 = buffer, size2 = size);
          size2 > 0;
         (buffer2 += header->bLength, size2 -= header->bLength)) {
        //循环得到每个接口长度和可选设置
        if (size2 < sizeof(struct usb_descriptor_header)) {
            dev_warn(ddev, "config %d descriptor has %d excess "
                "byte%s, ignoring\n",
                cfgno, size2, plural(size2));
            break;
        }

        header = (struct usb_descriptor_header *) buffer2;
        /*描述符头,便于通用分析
        struct usb_descriptor_header {
            __u8  bLength;
            __u8  bDescriptorType;
        } __attribute__ ((packed));
        */
        if ((header->bLength > size2) || (header->bLength < 2)) {
            dev_warn(ddev, "config %d has an invalid descriptor "
                "of length %d, skipping remainder of the config\n",
                cfgno, header->bLength);
            break;
        }

        if (header->bDescriptorType == USB_DT_INTERFACE) { //如果类型是接口描述符
        //一个接口描述符就代表了接口拥有某个一个设置,没有什么所谓的设置描述符
            struct usb_interface_descriptor *d;
            int inum;

            d = (struct usb_interface_descriptor *) header;
            if (d->bLength < USB_DT_INTERFACE_SIZE) {
                dev_warn(ddev, "config %d has an invalid "
                    "interface descriptor of length %d, "
                    "skipping\n", cfgno, d->bLength);
                continue;
            }

            inum = d->bInterfaceNumber; 
            //表明当前接口描述符(多个设置中的一个)属于哪个接口
            if (inum >= nintf_orig)
                dev_warn(ddev, "config %d has an invalid "
                    "interface number: %d but max is %d\n",
                    cfgno, inum, nintf_orig - 1);

            /* Have we already encountered this interface?
             * Count its altsettings */
            for (i = 0; i < n; ++i) {
                if (inums[i] == inum)
                    break;
            }
            if (i < n) {
                if (nalts[i] < 255)
                    ++nalts[i];
            } else if (n < USB_MAXINTERFACES) {
                inums[n] = inum;
                nalts[n] = 1;
                ++n;
            }
            //使用inums和nalts数组来记录接口号及其可选设置数量,n表示接口数量

        } else if (header->bDescriptorType ==
                USB_DT_INTERFACE_ASSOCIATION) { //针对复合设备的的描述符
            if (iad_num == USB_MAXIADS) {
                dev_warn(ddev, "found more Interface "
                           "Association Descriptors "
                           "than allocated for in "
                           "configuration %d\n", cfgno);
            } else {
                config->intf_assoc[iad_num] =
                    (struct usb_interface_assoc_descriptor
                    *)header;
                iad_num++;
            }

        } else if (header->bDescriptorType == USB_DT_DEVICE ||
                header->bDescriptorType == USB_DT_CONFIG)
            dev_warn(ddev, "config %d contains an unexpected "
                "descriptor of type 0x%X, skipping\n",
                cfgno, header->bDescriptorType);

    }   /* for ((buffer2 = buffer, size2 = size); ...) */
    size = buffer2 - buffer;
    config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
    //数组修正,buffer中可能会包含一些无效内容,这里只记录有效内容

    if (n != nintf)
        dev_warn(ddev, "config %d has %d interface%s, different from "
            "the descriptor's value: %d\n",
            cfgno, n, plural(n), nintf_orig);
    else if (n == 0)
        dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
    config->desc.bNumInterfaces = nintf = n;
    //如果解析出来的接口数量有异常,要进行警告

    /* Check for missing interface numbers */
    for (i = 0; i < nintf; ++i) {
        for (j = 0; j < nintf; ++j) {
            if (inums[j] == i)
                break;
        }
        if (j >= nintf)
            dev_warn(ddev, "config %d has no interface number "
                "%d\n", cfgno, i);
    }
    //查看是否遗漏了哪个接口号,进行警告

    /* Allocate the usb_interface_caches and altsetting arrays */
    for (i = 0; i < nintf; ++i) {
    //遍历每个接口号
        j = nalts[i];
        if (j > USB_MAXALTSETTING) {
            dev_warn(ddev, "too many alternate settings for "
                "config %d interface %d: %d, "
                "using maximum allowed: %d\n",
                cfgno, inums[i], j, USB_MAXALTSETTING);
            nalts[i] = j = USB_MAXALTSETTING;
        }
        //获取每个接口的可选设置数
        len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
        config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
        //为usb_host_config->intf_cache[i](struct usb_interface_cache *类型)开辟可选设置的接口空间
        /*usb_interface_cache内容如下
        struct usb_interface_cache {
            unsigned num_altsetting;    /* number of alternate settings 
            struct kref ref;        /* reference counter 

            /* variable-length array of alternate settings for this interface,
             * stored in no particular order 
            struct usb_host_interface altsetting[0];
        };
        */
        if (!intfc)
            return -ENOMEM;
        kref_init(&intfc->ref);
    }

    /* Skip over any Class Specific or Vendor Specific descriptors;
     * find the first interface descriptor */
    config->extra = buffer;
    //配置描述符后面还可能接class-和vendor-specific描述符,夹在配置描述符和接口描述符之间
    //不管有没有,先把buffer地址赋给extra,如果没有则下一行返回的i等于0,extralen为0
    i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
        USB_DT_INTERFACE, &n);
    //在buffer中寻找配置描述赋予后面跟着的第一个接口描述符
    config->extralen = i;
    if (n > 0)
        dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
            n, plural(n), "configuration");
    buffer += i;
    size -= i;
    //进行buffer指针和size的修正,如果中间存在class-和vendor-specific描述符会被忽略掉
    //此时buffer第一个肯定是接口描述符

    /* Parse all the interface/altsetting descriptors */
    while (size > 0) {
        retval = usb_parse_interface(ddev, cfgno, config,
            buffer, size, inums, nalts);
            //解析所有的接口/可选设置,详见下文
        if (retval < 0)
            return retval;

        buffer += retval;
        size -= retval;
    }

    /* Check for missing altsettings */
    for (i = 0; i < nintf; ++i) {
        intfc = config->intf_cache[i];
        for (j = 0; j < intfc->num_altsetting; ++j) {
            for (n = 0; n < intfc->num_altsetting; ++n) {
                if (intfc->altsetting[n].desc.
                    bAlternateSetting == j)
                    break;
            }
            if (n >= intfc->num_altsetting)
                dev_warn(ddev, "config %d interface %d has no "
                    "altsetting %d\n", cfgno, inums[i], j);
        }
    }
    //警告有没有哪个设置被遗漏了

    return 0;
}

其中usb_parse_interface实现如下:

static int usb_parse_interface(struct device *ddev, int cfgno,
    struct usb_host_config *config, unsigned char *buffer, int size,
    u8 inums[], u8 nalts[])
{
    unsigned char *buffer0 = buffer;
    struct usb_interface_descriptor *d;
    int inum, asnum;
    struct usb_interface_cache *intfc;
    struct usb_host_interface *alt;
    int i, n;
    int len, retval;
    int num_ep, num_ep_orig;

    d = (struct usb_interface_descriptor *) buffer;
    //将接口描述符
    buffer += d->bLength;
    size -= d->bLength;
    //buffer位置前移

    if (d->bLength < USB_DT_INTERFACE_SIZE)
        goto skip_to_next_interface_descriptor;

    /* Which interface entry is this? */
    intfc = NULL;
    inum = d->bInterfaceNumber;
    for (i = 0; i < config->desc.bNumInterfaces; ++i) {
        if (inums[i] == inum) {
            intfc = config->intf_cache[i];
            //获取接口号对应的intf_cache(struct usb_interface_cache *类型)
            break;
        }
    }
    if (!intfc || intfc->num_altsetting >= nalts[i])
        goto skip_to_next_interface_descriptor;

    /* Check for duplicate altsetting entries */
    asnum = d->bAlternateSetting;
    for ((i = 0, alt = &intfc->altsetting[0]);
          i < intfc->num_altsetting;
         (++i, ++alt)) {
        if (alt->desc.bAlternateSetting == asnum) {
            dev_warn(ddev, "Duplicate descriptor for config %d "
                "interface %d altsetting %d, skipping\n",
                cfgno, inum, asnum);
            goto skip_to_next_interface_descriptor;
        }
    }
    //查看该接口的设置是否存在过(设置编号是否一样)

    ++intfc->num_altsetting;
    memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);
    //进行intf_cache的数据赋值

    /* Skip over any Class Specific or Vendor Specific descriptors;
     * find the first endpoint or interface descriptor */
    alt->extra = buffer;
    //接口描述符后面还可能跟着class-或者vendor-specific描述符,先赋值给extra
    //如果没有下面find_next_descriptor会返回0
    i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
        USB_DT_INTERFACE, &n);
    //找到下一个端点或者接口描述符,因为有可能一个接口只有端点0,那么接口描述符后面可能不会跟着端点描述符
    alt->extralen = i;
    //extralen设置,如果没有class-或者vendor-specific,那么该值就是0
    if (n > 0)
        dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
            n, plural(n), "interface");
    buffer += i;
    size -= i;
    //buffer指针和size位置修改,略过class-或者vendor-specifi描述符

    /* Allocate space for the right(?) number of endpoints */
    num_ep = num_ep_orig = alt->desc.bNumEndpoints;
    //获取可选设置的端点数量
    alt->desc.bNumEndpoints = 0;        // Use as a counter
    if (num_ep > USB_MAXENDPOINTS) {
        dev_warn(ddev, "too many endpoints for config %d interface %d "
            "altsetting %d: %d, using maximum allowed: %d\n",
            cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
        num_ep = USB_MAXENDPOINTS;
    }

    if (num_ep > 0) {   /* Can't allocate 0 bytes */
        len = sizeof(struct usb_host_endpoint) * num_ep;
        alt->endpoint = kzalloc(len, GFP_KERNEL);
        if (!alt->endpoint)
            return -ENOMEM;
    }
    //开辟端点数量的struct usb_host_endpoint控件
    //为可选设置usb_host_interface->endpoint(usb_host_endpoint *类型)赋值

    /* Parse all the endpoint descriptors */
    n = 0;
    while (size > 0) {
        if (((struct usb_descriptor_header *) buffer)->bDescriptorType
             == USB_DT_INTERFACE)
            break;
        retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
            num_ep, buffer, size);
            //解析端点描述符,不再展开,就是构建struct usb_endpoint_descriptor
            //给alt(usb_host_interface *)->endpoint[ep->desc.bNumEndpoints]赋值
        if (retval < 0)
            return retval;
        ++n;

        buffer += retval;
        size -= retval;
    }

    if (n != num_ep_orig)
        dev_warn(ddev, "config %d interface %d altsetting %d has %d "
            "endpoint descriptor%s, different from the interface "
            "descriptor's value: %d\n",
            cfgno, inum, asnum, n, plural(n), num_ep_orig);
    return buffer - buffer0;

skip_to_next_interface_descriptor:
    i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
        USB_DT_INTERFACE, NULL);
    return buffer - buffer0 + i;
}
4.1.4.1 device_register->device_add

device_add是device_register函数的Part2,首先从device_register进行分析,实现如下:

/**
 *  device_register - register a device with the system.
 *  @dev:   pointer to the device structure
 *
 *  This happens in two clean steps - initialize the device
 *  and add it to the system. The two steps can be called
 *  separately, but this is the easiest and most common.
 *  I.e. you should only call the two helpers separately if
 *  have a clearly defined need to use and refcount the device
 *  before it is added to the hierarchy.
 */

int device_register(struct device *dev)
{
    device_initialize(dev);
    //设备初始化
    return device_add(dev);
    //设备添加到系统中
}

void device_initialize(struct device *dev)
{
    kobj_set_kset_s(dev, devices_subsys);
    //设置struct device->kobj(kobject类型).kset(kset类型)为预定义的devices_subsys
    //应该就是/sys/devices
    kobject_init(&dev->kobj);
    klist_init(&dev->klist_children, klist_children_get,
           klist_children_put);
    INIT_LIST_HEAD(&dev->dma_pools);
    INIT_LIST_HEAD(&dev->node);
    init_MUTEX(&dev->sem);
    spin_lock_init(&dev->devres_lock);
    INIT_LIST_HEAD(&dev->devres_head);
    device_init_wakeup(dev, 0);
    set_dev_node(dev, -1);
    //初始化struct device的各个成员
}
/**
 *  device_add - add device to device hierarchy.
 *  @dev:   device.
 *
 *  This is part 2 of device_register(), though may be called
 *  separately _iff_ device_initialize() has been called separately.
 *
 *  This adds it to the kobject hierarchy via kobject_add(), adds it
 *  to the global and sibling lists for the device, then
 *  adds it to the other relevant subsystems of the driver model.
 */
int device_add(struct device *dev)
{
    struct device *parent = NULL;
    struct class_interface *class_intf;
    int error = -EINVAL;

    dev = get_device(dev);
    //增加引用计数
    if (!dev || !strlen(dev->bus_id))
        goto Error;

    pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);

    parent = get_device(dev->parent);
    //获取parent,顺便增加parent的引用计数
    error = setup_parent(dev, parent);
    //设置struct device->kobj.parent,有可能是所属class的kobj
    if (error)
        goto Error;

    /* first, register with generic layer. */
    kobject_set_name(&dev->kobj, "%s", dev->bus_id);
    //设置device->kobj.k_name为struct device->bus_id
    //按照前文描述,就是usb1、usb2或者1-1、1-1.1
    error = kobject_add(&dev->kobj);
    //kobject_add:
            //如果kobject->kset存在:
                //将kobject->entry(list_head类型)添加到kobject->kset->list中
                //如果kobject->parent不存在,设置parent就是kobject->kset->kobject
                //这里就是预定义的devices_subsys
            //create_dir(kobject)->sysfs_create_dir(kobject)
                //创建sysfs目录,如果存在parent就在该parent目录下创建,如果不存在就在sys根下创建
                //这里就是在bus_subsys下创建
    if (error)
        goto Error;

    /* notify platform of device entry */
    if (platform_notify)
        platform_notify(dev);

    /* notify clients of device entry (new way) */
    if (dev->bus)
        blocking_notifier_call_chain(&dev->bus->bus_notifier,
                         BUS_NOTIFY_ADD_DEVICE, dev);

    error = device_create_file(dev, &uevent_attr);
    //sysfs操作:创建属性文件uevent
    if (error)
        goto attrError;

    if (MAJOR(dev->devt)) {
        error = device_create_file(dev, &devt_attr);
        //sysfs操作:创建属性文件devt
        if (error)
            goto ueventattrError;
    }

    error = device_add_class_symlinks(dev);
    //sysfs操作:创建符号链接subsystem、device
    if (error)
        goto SymlinkError;
    error = device_add_attrs(dev);
    //sysfs操作:device->class(struct class类型)->dev_attrs
    //sysfs操作:device->type(device_type类型)->groups
    //sysfs操作:device->groups
    if (error)
        goto AttrsError;
    error = dpm_sysfs_add(dev);
    //电源管理
    if (error)
        goto PMError;
    device_pm_add(dev);
    //电源管理
    error = bus_add_device(dev);
    //sysfs操作:为device创建device->bus_type->dev_attrs[]属性文件
    //sysfs操作:为device创建链接文件device->bus_id,值为usb1、usb2或者1-1、1-1.1
    //sysfs操作:为device创建链接文件"subsystem",值为device->bus_type->subsys,kobj
    //sysfs操作:为device创建链接文件"bus",值为device->bus_type->subsys,kobj
    if (error)
        goto BusError;
    kobject_uevent(&dev->kobj, KOBJ_ADD);
    //向用户空间报告uevent事件
    bus_attach_device(dev);
    //向总线添加设备,详见下文
    if (parent)
        klist_add_tail(&dev->knode_parent, &parent->klist_children);
    //将该struct device添加到parent->klist_children中
    if (dev->class) {  //如果存在所属class,也进行class相关链表添加,及其他操作
        down(&dev->class->sem);
        /* tie the class to the device */
        list_add_tail(&dev->node, &dev->class->devices);

        /* notify any interfaces that the device is here */
        list_for_each_entry(class_intf, &dev->class->interfaces, node)
            if (class_intf->add_dev)
                class_intf->add_dev(dev, class_intf);
        up(&dev->class->sem);
    }
 Done:
    put_device(dev);
    return error;
 BusError:
    device_pm_remove(dev);
    dpm_sysfs_remove(dev);
 PMError:
    if (dev->bus)
        blocking_notifier_call_chain(&dev->bus->bus_notifier,
                         BUS_NOTIFY_DEL_DEVICE, dev);
    device_remove_attrs(dev);
 AttrsError:
    device_remove_class_symlinks(dev);
 SymlinkError:
    if (MAJOR(dev->devt))
        device_remove_file(dev, &devt_attr);

    if (dev->class) {
        sysfs_remove_link(&dev->kobj, "subsystem");
        /* If this is not a "fake" compatible device, remove the
         * symlink from the class to the device. */
        if (dev->kobj.parent != &dev->class->subsys.kobj)
            sysfs_remove_link(&dev->class->subsys.kobj,
                      dev->bus_id);
        if (parent) {
#ifdef CONFIG_SYSFS_DEPRECATED
            char *class_name = make_class_name(dev->class->name,
                               &dev->kobj);
            if (class_name)
                sysfs_remove_link(&dev->parent->kobj,
                          class_name);
            kfree(class_name);
#endif
            sysfs_remove_link(&dev->kobj, "device");
        }
    }
 ueventattrError:
    device_remove_file(dev, &uevent_attr);
 attrError:
    kobject_uevent(&dev->kobj, KOBJ_REMOVE);
    kobject_del(&dev->kobj);
 Error:
    if (parent)
        put_device(parent);
    goto Done;
}

bus_attach_device实现如下:

void bus_attach_device(struct device * dev)
{
    struct bus_type *bus = dev->bus;
    int ret = 0;

    if (bus) {
        dev->is_registered = 1;
        if (bus->drivers_autoprobe)
            ret = device_attach(dev);
            //将设备attach到驱动上,实现见下文
        WARN_ON(ret < 0);
        if (ret >= 0)
            klist_add_tail(&dev->knode_bus, &bus->klist_devices);
            //将设备添加到总线的设备链表中
        else
            dev->is_registered = 0;
    }
}

int device_attach(struct device * dev)
{
    int ret = 0;

    down(&dev->sem);
    if (dev->driver) { 
        ret = device_bind_driver(dev);
        //如果已经存在驱动,那么就直接调用device_bind_driver
            //sysfs操作
            //将device->knode_driver添加到driver的klist_devices链表中
        if (ret == 0)
            ret = 1;
        else {
            dev->driver = NULL;
            ret = 0;
        }
    } else {  
        ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
        //如果没有存在驱动,调用bus_for_each_drv
            //遍历bus_type->klist_drivers中每一个驱动对象,调用__device_attach函数,见下文
    }
    up(&dev->sem);
    return ret;
}

static int __device_attach(struct device_driver * drv, void * data)
{
    struct device * dev = data;
    return driver_probe_device(drv, dev);
    //实现见下
}

int driver_probe_device(struct device_driver * drv, struct device * dev)
{
    int ret = 0;

    if (!device_is_registered(dev))
        return -ENODEV;
    if (drv->bus->match && !drv->bus->match(dev, drv))
        goto done;
    //如果总线存在match函数,调用总线的match函数,就是之前分析的usb_device_match函数
    pr_debug("%s: Matched Device %s with Driver %s\n",
         drv->bus->name, dev->bus_id, drv->name);

    ret = really_probe(dev, drv);
    //如果总线存在probe函数,那么就调用总线的probe函数,usb_bus_type没有probe函数
    //否则,如果驱动存在probe函数,那么就调用驱动的probe函数

done:
    return ret;
}

4.2. 设备与驱动的match与probe

4.2.1. 设备驱动usb_generic_driver & usb_bus_type->match

前面分析过usb_generic_driver和usb_bus_type如下

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,
};
//之前分析过,注册该驱动时,设置的是针对设备,而非接口
struct bus_type usb_bus_type = {
    .name =     "usb",
    .match =    usb_device_match,
    .uevent =   usb_uevent,
    .suspend =  usb_suspend,
    .resume =   usb_resume,
};
//没有probe指针,如果设备和驱动匹配,就需要调用驱动的probe函数,这里调用的是device_driver->probe函数

usb_bus_type的match函数usb_device_match前面分析过,基本来说就是,如果是USB设备,那么只要驱动是USB 设备类型的即可,如下:

struct device_type usb_device_type = {
    .name =     "usb_device",
    .release =  usb_release_dev,
    .uevent =   usb_dev_uevent,
};

如果是USB接口,那么就需要遍历接口驱动usb_driver中的id_table和dynids,针对每一个usb_device_id的match_flags,和usb_device中设备描述符及usb_interface当前设置usb_host_interface中接口描述符信息进行匹配

所以当一个USB设备注册到总线后,肯定会匹配到usb_generic_driver,然后调用usb_generic_driver(usb_device_driver类型)->drvwrap(usbdrv_wrap类型)->driver(device_driver类型)->probe函数,在usb_register_device_driver时进行过设置,该probe函数为usb_probe_device

同样当一个USB接口注册到总线后,匹配到对应的接口驱动(调用usb_register进行注册,该函数调用usb_register_driver,会设置device_driver->probe为usb_probe_interface),然后调用usb_driver->drvwrap(usbdrv_wrap类型)->driver(device_driver类型)->probe函数,也就是usb_probe_interface

4.2.2. 设备驱动usb_generic_driver中device_driver->probe(usb_probe_device)

usb_probe_device实现如下:

static int usb_probe_device(struct device *dev)
{
    struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
    //获取所属usb_device_driver,也就是usb_generic_driver
    struct usb_device *udev;
    int error = -ENODEV;

    dev_dbg(dev, "%s\n", __FUNCTION__);

    if (!is_usb_device(dev))    /* Sanity check */
    //确保是设备类型,而不是接口类型
        return error;

    udev = to_usb_device(dev);
    //获取所在的usb_device
    /* TODO: Add real matching code */

    /* The device should always appear to be in use
     * unless the driver suports autosuspend.
     */
    udev->pm_usage_cnt = !(udriver->supports_autosuspend);

    error = udriver->probe(udev);
    //调用usb_device_driver->probe函数
    //也就是usb_generic_driver的probe函数generic_probe
    return error;
}
4.2.3. 设备驱动usb_generic_driver->probe(generic_probe)
static int generic_probe(struct usb_device *udev)
{
    int err, c;

    /* put device-specific files into sysfs */
    usb_create_sysfs_dev_files(udev);
    //sysfs操作
    /* Choose and set the configuration.  This registers the interfaces
     * with the driver core and lets interface drivers bind to them.
     */
    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;
}

usb_choose_configuration实现如下:

int usb_choose_configuration(struct usb_device *udev)
{
    int i;
    int num_configs;
    int insufficient_power = 0;
    struct usb_host_config *c, *best;

    best = NULL;
    c = udev->config;
    //所有可选配置指针
    num_configs = udev->descriptor.bNumConfigurations;
    //可选配置数
    for (i = 0; i < num_configs; (i++, c++)) {
        //循环遍历,获得最优配置
        struct usb_interface_descriptor *desc = NULL;

        /* It's possible that a config has no interfaces! */
        if (c->desc.bNumInterfaces > 0)
            desc = &c->intf_cache[0]->altsetting->desc;
        //获取intf_cache接口缓存中第一个接口的第一个可选设置的接口描述符
        /*
         * HP's USB bus-powered keyboard has only one configuration
         * and it claims to be self-powered; other devices may have
         * similar errors in their descriptors.  If the next test
         * were allowed to execute, such configurations would always
         * be rejected and the devices would not work as expected.
         * In the meantime, we run the risk of selecting a config
         * that requires external power at a time when that power
         * isn't available.  It seems to be the lesser of two evils.
         *
         * Bugzilla #6448 reports a device that appears to crash
         * when it receives a GET_DEVICE_STATUS request!  We don't
         * have any other way to tell whether a device is self-powered,
         * but since we don't use that information anywhere but here,
         * the call has been removed.
         *
         * Maybe the GET_DEVICE_STATUS call and the test below can
         * be reinstated when device firmwares become more reliable.
         * Don't hold your breath.
         */
#if 0  //忽略
        /* Rule out self-powered configs for a bus-powered device */
        if (bus_powered && (c->desc.bmAttributes &
                    USB_CONFIG_ATT_SELFPOWER))
            continue;
#endif

        /*
         * The next test may not be as effective as it should be.
         * Some hubs have errors in their descriptor, claiming
         * to be self-powered when they are really bus-powered.
         * We will overestimate the amount of current such hubs
         * make available for each port.
         *
         * This is a fairly benign sort of failure.  It won't
         * cause us to reject configurations that we should have
         * accepted.
         */

        /* Rule out configs that draw too much bus current */
        if (c->desc.bMaxPower * 2 > udev->bus_mA) {
            insufficient_power++;
            continue;
        }
        //如果配置所需电流超出hub可提供电流,则略过

        /* When the first config's first interface is one of Microsoft's
         * pet nonstandard Ethernet-over-USB protocols, ignore it unless
         * this kernel has enabled the necessary host side driver.
         */
        if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) {
#if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
            continue;
#else
            best = c;
#endif
        }
        //配置选择规则1:第一个配置的第一个接口是一个微软pet nonstandard Ethernet-over-USB protocols,如果kernel中做了设置,则优先选择

        /* 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;
        }
        //配置选择规则2:设备描述符中的non-vendor-specific类

        /* If all the remaining configs are vendor-specific,
         * choose the first one. */
        else if (!best)
        //如果剩下的全是vendor-specific的,则选择第一个
            best = c;
    }

    if (insufficient_power > 0)
        dev_info(&udev->dev, "rejected %d configuration%s "
            "due to insufficient available bus power\n",
            insufficient_power, plural(insufficient_power));

    if (best) {
        i = best->desc.bConfigurationValue;
        //最终返回选择最好配置的描述符中的bConfigurationValue
        dev_info(&udev->dev,
            "configuration #%d chosen from %d choice%s\n",
            i, num_configs, plural(num_configs));
    } else {
        i = -1;
        dev_warn(&udev->dev,
            "no configuration chosen from %d choice%s\n",
            num_configs, plural(num_configs));
    }
    return i;
}

usb_set_configuration实现如下:

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;

    if (dev->authorized == 0 || configuration == -1)
        configuration = 0;
        //如果没有可选配置,则设置配置号为0
        //规范中描述,配置号必须为0或者配置描述符中bConfigurationValue的值
        //如果配置号为0,则SET_CONFIGURATION后,设备还处于Address状态
    else {
        for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
            if (dev->config[i].desc.bConfigurationValue ==
                    configuration) {
                cp = &dev->config[i];
                //依据配置描述符的bConfigurationValue获取usb_host_config结构
                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;
    //开辟usb_interface指针数组
    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;
        }

        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;

    /* if it's already configured, clear out old state first.
     * getting rid of old interfaces means unbinding their drivers.
     */
    if (dev->state != USB_STATE_ADDRESS)
        usb_disable_device (dev, 1);    // Skip ep0
        //如果已经处于配置状态,则退回Address状态
        //首先将设备中所有端点都删除掉,然后将设备当前配置使用的每个接口都从系统中unregister掉

    if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
            USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
            NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
        //向设备发送请求,SET_CONFIGURATION
        /* All the old state is gone, so what else can we do?
         * The device is probably useless now anyway.
         */
        cp = NULL;
    }

    dev->actconfig = cp;
    //将激活的配置,赋值给usb_device->actconfig
    if (!cp) {
        usb_set_device_state(dev, USB_STATE_ADDRESS);
        usb_autosuspend_device(dev);
        goto free_interfaces;
        //如果目标配置为空,则将设备重置为Address状态,并释放相关结构
    }
    usb_set_device_state(dev, USB_STATE_CONFIGURED);
    //设置usb_device的状态为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);
        //为usb_host_config->interface数组赋值,使用intf_cache缓存数组中的数据来填充它

        alt = usb_altnum_to_altsetting(intf, 0);
        //获取0号可选设置
        //规范中说明,接口的默认设置总是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.
         */
        if (!alt)
            alt = &intf->altsetting[0];
        //如果没有拿到0号设置,就拿之前缓存的可选设置中第一项来充数

        intf->cur_altsetting = alt;
        //指定刚才拿到的设置为当前使用的设置

        usb_enable_interface(dev, intf);
        //enable接口:enable每个endpoint,分别获取端点地址、端点号、是否是控制断点
            //根据端点方向来初始化usb_device的ep_in和ep_out数组

        intf->dev.parent = &dev->dev;
        intf->dev.driver = NULL;
        intf->dev.bus = &usb_bus_type;
        intf->dev.type = &usb_if_device_type;
        intf->dev.dma_mask = dev->dev.dma_mask;
        //接口的struct device设置
        //parent为usb_device->dev(struct device类型)
        //设备类型为usb_if_device_type,总线类型为usb_bus_type
        device_initialize (&intf->dev);
        //初始化接口的struct device,之前分析过
        mark_quiesced(intf);
        //将接口的is_active标志初始化为0,表示还没有和任何驱动绑定
        sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
             dev->bus->busnum, dev->devpath,
             configuration, alt->desc.bInterfaceNumber);
    }
    kfree(new_interfaces);
    //释放指针数组,并不释放每一个数组项,已经赋值给了usb_host_config->interface[]

    if (cp->string == NULL)
        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 (i = 0; i < nintf; ++i) {
        struct usb_interface *intf = cp->interface[i];
        //遍历每个usb_interface
        dev_dbg (&dev->dev,
            "adding %s (config #%d, interface %d)\n",
            intf->dev.bus_id, configuration,
            intf->cur_altsetting->desc.bInterfaceNumber);
        ret = device_add (&intf->dev);
        //调用device_add,前面分析过,该函数最终会调用bus_attach_device(dev)向总线添加设备,后者首先调用device_attach(dev)将设备attach到驱动上,最后将设备添加到总线的设备链表中
        //device_attach函数会遍历总线usb_bus_type上的每个device_driver,调用其match函数,匹配成功的调用驱动(usb_register_driver注册的)中struct device_driver->probe函数
        //也就是usb_probe_interface函数
        if (ret != 0) {
            dev_err(&dev->dev, "device_add(%s) --> %d\n",
                intf->dev.bus_id, ret);
            continue;
        }
        usb_create_sysfs_intf_files(intf);
        //sysfs操作
    }

    usb_autosuspend_device(dev);
    return 0;
}
4.2.4. 接口驱动中struct device_driver->probe(usb_probe_interface)
static int usb_probe_interface(struct device *dev)
{
    struct usb_driver *driver = to_usb_driver(dev->driver);
    //获取所在的usb_driver
    struct usb_interface *intf;
    struct usb_device *udev;
    const struct usb_device_id *id;
    int error = -ENODEV;

    dev_dbg(dev, "%s\n", __FUNCTION__);

    if (is_usb_device(dev))     /* Sanity check */
        return error;
    //如果是usb设备,不是接口设备,直接返回错误

    intf = to_usb_interface(dev);
    udev = interface_to_usbdev(intf);
    //获取usb_interface和所在usb_device
    if (udev->authorized == 0) {
        dev_err(&intf->dev, "Device is not authorized for usage\n");
        return -ENODEV;
    }

    id = usb_match_id(intf, driver->id_table);
    if (!id)
        id = usb_match_dynamic_id(intf, driver);
    //获取匹配的usb_device_id
    if (id) {
        dev_dbg(dev, "%s - got id\n", __FUNCTION__);

        error = usb_autoresume_device(udev);
        //立即autoresume一个USB设备和它的接口
        if (error)
            return error;

        /* Interface "power state" doesn't correspond to any hardware
         * state whatsoever.  We use it to record when it's bound to
         * a driver that may start I/0:  it's not frozen/quiesced.
         */
        mark_active(intf);
        //设置struct usb_interface->is_active为1,表示驱动匹配成功
        intf->condition = USB_INTERFACE_BINDING;
        //修改绑定状态

        /* The interface should always appear to be in use
         * unless the driver suports autosuspend.
         */
        intf->pm_usage_cnt = !(driver->supports_autosuspend);

        error = driver->probe(intf, id);
        //驱动usb_driver的probe函数,这个函数就是每个定义为usb_driver自己的probe函数
        if (error) {
            mark_quiesced(intf);
            intf->needs_remote_wakeup = 0;
            intf->condition = USB_INTERFACE_UNBOUND;
        } else
            intf->condition = USB_INTERFACE_BOUND;

        usb_autosuspend_device(udev);
        //delayed autosuspend 一个USB设备和它的接口
    }

    return error;
}

最终会调用usb_driver->probe函数,就是各个接口驱动自己的定义了,需要针对不同驱动进行特例分析

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值