Chinaunix首页 | 论坛 | 博客
  • 博客访问: 643161
  • 博文数量: 151
  • 博客积分: 3498
  • 博客等级: 中校
  • 技术积分: 1570
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-28 18:10
文章分类

全部博文(151)

文章存档

2014年(12)

2013年(17)

2012年(17)

2011年(5)

2010年(12)

2009年(2)

2007年(26)

2006年(22)

2005年(38)

分类: LINUX

2005-11-17 18:44:22

    author:windguy
   license:GPL
       date:2005-11-17

USB驱动的注册过程总的来说要做如下的事情:首先把驱动连接到驱动链表中,然后开始扫描USB总线,从ROOT HUB开始,查找USB DEVICE,在查找的过程中使用深度遍历方法,即如果是HUB,则查找连接在HUB上的子设备,通过比较设备上的usb_interface 是否有驱动支持了,如果没有则扫描驱动链表,从驱动链表中取得驱动,通过驱动和USB DEVICE的usb_device_id进行匹配,如果匹配则调用驱动的probe函数探测,如果probe返回值不为NULL,将该驱动连接在设备的usb_interface 上。

1。注册驱动
首先把驱动连接到驱动链表中,然后开始扫描USB总线
int usb_register(struct usb_driver *new_driver)
{
    if (new_driver->fops != NULL) {
        if (usb_minors[new_driver->minor/16]) {
             err("error registering %s driver", new_driver->name);
            return -EINVAL;
        }
        usb_minors[new_driver->minor/16] = new_driver;
    }

    info("registered new driver %s", new_driver->name);

    init_MUTEX(&new_driver->serialize);

    /* Add it to the list of known drivers */
    list_add_tail(&new_driver->driver_list, &usb_driver_list);

    usb_scan_devices();

    return 0;
}
2。扫描总线链表,选取每一条总线,从总线所指向的ROOT HUB这个设备开始检查驱动是否被驱动所支持。
void usb_scan_devices(void)
{
    struct list_head *tmp;

    down (&usb_bus_list_lock);
    tmp = usb_bus_list.next;
    while (tmp != &usb_bus_list) {
        struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);

        tmp = tmp->next;
        usb_check_support(bus->root_hub);
    }
    up (&usb_bus_list_lock);
}
HUB也是USB DEVICE ,但不是HUB,而是真正的USB DEVICE。
static void usb_check_support(struct usb_device *dev)
{
    int i;

    if (!dev) {
        err("null device being checked!!!");
        return;
    }

    for (i=0; i        if (dev->children[i])
            usb_check_support(dev->children[i]);

    if (!dev->actconfig)
        return;

    /* now we check this device */
    if (dev->devnum > 0)
        for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
            usb_find_interface_driver(dev, i);
}
3。查看USB DEVICE 的接口是否被驱动所支持。
   *查看该接口是否已经被驱动了;
   *遍历驱动连表,匹配驱动和设备的usb_device_id;
   *匹配成功,调用驱动的probe 函数;
   *如果probe也探测成功,则把驱动分配给该接口;
 
static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
{
    struct list_head *tmp;
    struct usb_interface *interface;
    void *private;
    const struct usb_device_id *id;
    struct usb_driver *driver;
    int i;
   
    if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
        err("bad find_interface_driver params");
        return -1;
    }

    down(&dev->serialize);

    interface = dev->actconfig->interface + ifnum;

    if (usb_interface_claimed(interface))
        goto out_err;

    private = NULL;
    for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {
        driver = list_entry(tmp, struct usb_driver, driver_list);
        tmp = tmp->next;

        id = driver->id_table;
        /* new style driver? */
        if (id) {
            for (i = 0; i < interface->num_altsetting; i++) {
                  interface->act_altsetting = i;
                id = usb_match_id(dev, interface, id);
                if (id) {
                    down(&driver->serialize);
                    private = driver->probe(dev,ifnum,id);
                    up(&driver->serialize);
                    if (private != NULL)
                        break;
                }
            }

            /* if driver not bound, leave defaults unchanged */
            if (private == NULL)
                interface->act_altsetting = 0;
        } else { /* "old style" driver */
            down(&driver->serialize);
            private = driver->probe(dev, ifnum, NULL);
            up(&driver->serialize);
        }

        /* probe() may have changed the config on us */
        interface = dev->actconfig->interface + ifnum;

        if (private) {
            usb_driver_claim_interface(driver, interface, private);
            up(&dev->serialize);
            return 0;
        }
    }

out_err:
    up(&dev->serialize);
    return -1;
}
4。把驱动分配给接口。
将该驱动连接在设备的usb_interface 上,驱动的注册过程完成。
void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
{
    if (!iface || !driver)
        return;

    dbg("%s driver claimed interface %p", driver->name, iface);

    iface->driver = driver;
    iface->private_data = priv;
} /* usb_driver_claim_interface() */

5.驱动支持设备的问题研究
  * USB设备是一个可直接操作的设备:
  例子是扫描仪驱动,如果驱动的file operation 成员不为NULL,则该设备驱动直接被 USB_MAJOR 的驱动程序所支持。
#define USB_MAJOR 180 
而且在usb_register 的时候把驱动赋予usb_minors[new_driver->minor/16] = new_driver;所以你打开你的设备的话,通过次设备号从这个数组中取得驱动,通过该usb_minors数组相关驱动的file operation进行调用。
   *USB设备是一个视频设备 或者其它的等。
 则在驱动调用probe的时候注册为真正被支持的设备,如调用video_register_device注册为被视频驱动(V4L)所支持的设备类型。

6.参考
 *《LINUX 内核源代码情景分析》 毛德操、胡希明;
 

阅读(2272) | 评论(0) | 转发(0) |
0

上一篇:PCI卡驱动

下一篇:双链表的作用kernel:2.4.20

给主人留下些什么吧!~~