Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531385
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: 嵌入式

2009-07-16 14:26:12

浅析usb设备描述符读取usb_control_msg

hub_thread
==>hub_events
==*>hub_port_connect_change
==**>usb_new_device(udev); // 向/sys/bus/usb总线添加hub检测到的设备

usb_device_match将该udev和usb_generic_driver关联上,之后执行generic_probe函数,进一步
与使用usb_register注册的interface接口函数们,进行一一匹配,尝试获得驱动刚刚插入的usb设备[luther.gliethttp].

usb_generic_driver
==>generic_probe

struct bus_type usb_bus_type = {
    .name =        "usb",
    .match =    usb_device_match,
    .uevent =    usb_uevent,
    .suspend =    usb_suspend,
    .resume =    usb_resume,
};



hub_thread
==>hub_events
==*>hub_port_connect_change
    // hdev = hub->hdev即hdev对应hub,为该预申请的插入的usb设备udev的parent
    // usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
    udev = usb_alloc_dev(hdev, hdev->bus, port1); // 为插入的usb设备建立sys路径名,都是些内存操作
    udev->speed = USB_SPEED_UNKNOWN; // 设置speed为USB_SPEED_UNKNOWN,在后面的hub_port_reset中填入插入的usb设备具体值
    choose_address(udev); // 从udev->bus上面获取一个usb设备地址,开始使用0地址和插入的usb设备通信,之后将使用
    // 这里申请到的address与该usb设备通信.
    hub_port_init(hub, udev, port1, i); // 获取描述符
==**>hub_port_init
    hub_port_reset(hub, port1, udev, delay);==>set_port_feature

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)

// 发送usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),USB_REQ_SET_FEATURE, USB_RT_PORT
// 读取usb设备的speed类型信息,最后设置下面4种中的某一个具体值
// udev->speed = USB_SPEED_VARIABLE; 对应的udev->ep0.desc.wMaxPacketSize = 512字节
// udev->speed = USB_SPEED_HIGH;     对应的udev->ep0.desc.wMaxPacketSize = 64字节
// udev->speed = USB_SPEED_FULL;     对应的udev->ep0.desc.wMaxPacketSize = 64字节
// udev->speed = USB_SPEED_LOW;      对应的udev->ep0.desc.wMaxPacketSize = 8字节
    usb_control_msg(udev, usb_rcvaddr0pipe(),               // 使用0地址第1次获取设备描述符
                    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                    USB_DT_DEVICE << 8, 0,
                    buf, 64,
                    USB_CTRL_GET_TIMEOUT);
    hub_set_address(udev, devnum);                          // 发送addr地址给usb设备,之后hub将使用该地址与usb设备通信
    usb_get_device_descriptor(udev, 8);                     // 使用addr地址第2次获取设备描述符
    ==> usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                (USB_DT_DEVICE << 8) + index, 0, buf, size,
                USB_CTRL_GET_TIMEOUT);

status = usb_new_device(udev);
==>device_add(&udev->dev); // 将udev添加到usb-bus总线上,因为这个dev为

因为上面udev = usb_alloc_dev(hdev, hdev->bus, port1);时
==>dev->dev.bus = &usb_bus_type;设置dev为usb总线上的设备
==>dev->dev.type = &usb_device_type;设置该dev为usb设备而非接口
设置了类型为usb_device_type,
所以
device_add==>bus_attach_device(dev);为设备绑定驱动时,就会使用
struct bus_type usb_bus_type = {
    .name =        "usb",
    .match =    usb_device_match,
    .uevent =    usb_uevent,
    .suspend =    usb_suspend,
    .resume =    usb_resume,
};

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
    /* devices and interfaces are handled separately */
    if (is_usb_device(dev)) {
        // 会发现他是一个device而直接返回1
         // dev为设备,

        /* interface drivers never match devices */
        if (!is_usb_device_driver(drv))
            return 0; // driver为interface的话就返回0

        /* TODO: Add real matching code */
        return 1; // ok, driver也是device驱动

    } else {
        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; // dev为interface设备,所以需要interface驱动

        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;
}

subsys_initcall(usb_init);
==>usb_init
==>usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
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,
};
==>generic_probe  // 为设备的probe函数
==>usb_set_configuration // 生成该设置配置描述下的所有接口描述符所描述的接口dev对象
==>ret = device_add(&intf->dev);



/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;

    __le16 bcdUSB;
    __u8  bDeviceClass;
    __u8  bDeviceSubClass;
    __u8  bDeviceProtocol;
    __u8  bMaxPacketSize0;
    __le16 idVendor;
    __le16 idProduct;
    __le16 bcdDevice;
    __u8  iManufacturer;
    __u8  iProduct;
    __u8  iSerialNumber;
    __u8  bNumConfigurations;
} __attribute__ ((packed));

#define USB_DT_DEVICE_SIZE        18
 

/*
 * Descriptor types ... USB 2.0 spec table 9.5
 */
#define USB_DT_DEVICE            0x01
#define USB_DT_CONFIG            0x02
#define USB_DT_STRING            0x03
#define USB_DT_INTERFACE        0x04
#define USB_DT_ENDPOINT            0x05
#define USB_DT_DEVICE_QUALIFIER        0x06
#define USB_DT_OTHER_SPEED_CONFIG    0x07
#define USB_DT_INTERFACE_POWER        0x08
/* these are from a minor usb 2.0 revision (ECN) */
#define USB_DT_OTG            0x09
#define USB_DT_DEBUG            0x0a
#define USB_DT_INTERFACE_ASSOCIATION    0x0b
/* these are from the Wireless USB spec */
#define USB_DT_SECURITY            0x0c
#define USB_DT_KEY            0x0d
#define USB_DT_ENCRYPTION_TYPE        0x0e
#define USB_DT_BOS            0x0f
#define USB_DT_DEVICE_CAPABILITY    0x10
#define USB_DT_WIRELESS_ENDPOINT_COMP    0x11
#define USB_DT_WIRE_ADAPTER        0x21
#define USB_DT_RPIPE            0x22
阅读(7823) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~