linux USB子系统

转载地址:http://blog.csdn.net/Deadline_h/article/details/78709142

1.usb总线设备模型

linux usb子系统使用的总线设备驱动模型。 
在linux内核里有一条usb总线为usb_bus_type

struct bus_type usb_bus_type = {
    .name =     "usb",
    .match =    usb_device_match,
    .uevent =   usb_uevent,
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在该总线下挂有usb设备和usb驱动。 
根据设备和驱动的类型又分为两大类 
一类为usb设备,一类为usb接口设备。 
usb设备和usb设备驱动进行匹配,usb接口设备和usb接口驱动进行匹配。 
通过match函数,这两类的匹配进入不同的分支

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
    /* devices and interfaces are handled separately 设备和接口设备分开处理*/
    if (is_usb_device(dev)) {//usb设备

        /* interface drivers never match devices */
        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 */
        if (is_usb_device_driver(drv)) // ==0代表接口驱动 非0代表设备驱动
            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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

/* ———————————————— */ 
usb接口设备(设备类型 == usb_if_device_type) 通过 device_add注册 
usb接口驱动(struct usb_driver ,需要我们实现) 通过 usb_register 注册 
/* ———————————————— */ 
usb设备(设备类型 == usb_device_type) 通过 device_add 注册 
usb设备驱动() 通过usb_register_device_driver()注册

2.usb设备接入过程

1、usb设备插入usb接口,usb差分信号线上电平变化,导致usb控制器产生中断hub_irq,通知系统有usb设备接入。
2、usb hub线程(hub_thread)被hub_irq唤醒,发生如下函数调用
hub_irq
    kick_khubd
        hub_thread
            hub_events
                hub_port_connect_change//端口连接发生改变
                    udev = usb_alloc_dev//分配一个usb设备
                    hub_port_init//获取设备描述符
                    usb_new_device(udev)
                        usb_enumerate_device//枚举设备
                            usb_get_configuration//获取配置描述符
                                for(; cfgno < ncfg; cfgno++)//有多少个配置都获取出来
                                {
                                    usb_get_descriptor //获取配置描述符,得到大小                               
                                    usb_parse_configuration//解析配置描述符    
                                        usb_parse_interface//解析接口描述符
                                            usb_parse_endpoint//解析端点描述符                                     
                                }
                        device_add(注册的设备类型是:usb_device_type) //调用usb_bus_type->match函数,如果匹配成功,会导致usb_device_driver的probe函数被调用                                               
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

usb设备驱动在哪里注册? 
在/driver/usb/core/usb.c注册

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_init
    usb_register_device_driver(&usb_generic_driver )
        generic_probe //如果跟usb设备匹配上的话,会导致probe函数被调用
            usb_set_configuration //设置配置
                for (i = 0; i < nintf; ++i) //有多少个接口,就注册多少个usb_if_device_type接口设备
                {       
                    struct usb_interface *intf = cp->interface[i];
                    。。。
                    intf->dev.bus = &usb_bus_type;
                    intf->dev.type = &usb_if_device_type;//usb接口设备
                    ret = device_add(&intf->dev);   // 把device放入usb_bus_type的dev链表,                             
                                                // 从 usb_bus_type 的driver链表里取出usb_driver,                       
                                                // 把usb_interface和usb_driver的id_table比较
                                                // 如果能匹配,调用usb_driver的probe 
                                                // 所以一个接口就对应一个usb驱动
                。。。
                }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

从上述代码中可知,在接入usb设备引发如下事件 
注册usb设备 -> 根据usb设备的接口描述符,注册usb接口设备(有多少个接口就有多少个usb接口设备) 
所以我们要实现接口设备驱动用来驱动usb接口设备(类型为usb_if_device_type的设备)

3 usb接口设备驱动编写

参考:h:\linux_source_code\linux-3.0.1\drivers\hid\usbhid\Usbmouse.c

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_host_interface *interface;
    struct usb_endpoint_descriptor *endpoint;
    int pipe;

    interface = intf->cur_altsetting;
    endpoint = &interface->endpoint[0].desc;

    /* a. 分配一个input_dev */
    uk_dev = input_allocate_device();

    /* b. 设置 */
    /* b.1 能产生哪类事件 */
    set_bit(EV_KEY, uk_dev->evbit);
    set_bit(EV_REP, uk_dev->evbit);

    /* b.2 能产生哪些事件 */
    set_bit(KEY_L, uk_dev->keybit);
    set_bit(KEY_S, uk_dev->keybit);
    set_bit(KEY_ENTER, uk_dev->keybit);

    /* c. 注册 */
    input_register_device(uk_dev);

    /* d. 硬件相关操作 */
    /* 数据传输3要素: 源,目的,长度 */
    /* 源: USB设备的某个端点 */
    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

    /* 长度: */
    len = endpoint->wMaxPacketSize;

    /* 目的: */
    usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);

    /* 使用"3要素" */
    /* 分配usb request block */
    uk_urb = usb_alloc_urb(0, GFP_KERNEL);
    /* 使用"3要素设置urb" */
    usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);
    uk_urb->transfer_dma = usb_buf_phys;
    uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    /* 使用URB */
    usb_submit_urb(uk_urb, GFP_KERNEL);

    return 0;
}

//接口匹配idtable
static struct usb_device_id usb_mouse_id_table [] = {
        { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
            USB_INTERFACE_PROTOCOL_MOUSE) },
        { } /* Terminating entry */
};
//usb接口驱动结构体
static struct usb_driver usb_mouse_driver = {
    .name       = "usbmouse",
    .probe      = usb_mouse_probe,
    .disconnect = usb_mouse_disconnect,
    .id_table   = usb_mouse_id_table,
};

static int __init usb_mouse_init(void)
{
    int retval = usb_register(&usb_mouse_driver);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

大致讲这么多,仅供参考。

你可能感兴趣的:(linux USB子系统)