Chinaunix首页 | 论坛 | 博客
  • 博客访问: 656867
  • 博文数量: 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-21 20:15:13

从USB驱动的注册谈链表!!

在drivers/usb/usb.c文件中
其中有两个链表;一个是USB驱动的链表,一个是USB总线的链表。链表头声明为:
LIST_HEAD(usb_driver_list);
LIST_HEAD(usb_bus_list);

其中LIST_HEAD是声明在include/linux/list.h文件中的。

#define LIST_HEAD(name)
    struct list_head name = LIST_HEAD_INIT(name)
结构struct list_head 定义如下:
typedef struct list_head {
    struct list_head *next, *prev;
} list_t;
而LIST_HEAD_INIT是一个初始化的宏,作用把链表头的两个成员都指向自己。
#define LIST_HEAD_INIT(name) { &(name), &(name) }


1。注册驱动到USB驱动链表中。
   该函数把新的驱动添加到驱动链表中,当然usb_driver_list这个链表是连接了struct usb_driver的一个成员 driver_list.
int usb_register(struct usb_driver *new_driver)
{
    /* Add it to the list of known drivers */
    list_add_tail(&new_driver->driver_list, &usb_driver_list);
    return 0;
}
函数   void list_add_tail(struct list_head *new, struct list_head *head)  的作用把new 插在head的前面。
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}
static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}


初始化链表头时候的状态:
  usb_driver_list<-----usb_driver_list------>usb_driver_list
插入一个新的list_head后,结构变为:
  usb_driver_list<-----new<------usb_driver_list------>usb_driver_list
在usb_driver_list和usb_driver_list的prev指向的list_head之前插入了一个新的结构。

 
2.从USB驱动链表中取得usb_driver结构
从链表中查找每一个驱动,在usb_driver_list的下一个list_head 才是真的struct usb_driver的数据成员,所以tmp=usb_driver_list.next;

即是从下一个开始寻找驱动,为什么tmp!=&usb_driver_list呢,可知道在usb_driver_list初始化为该链表头的时候,他的两个成员都是指向

它自己吗.
  static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
{
    struct list_head *tmp;   
    struct usb_driver *driver;

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


3。从USB总线结构链表中取得struct usb_bus 结构的总线数据结构。
在usb_bus_list的下一个list_head 才是真的struct usb_bus的数据成员,所以tmp=usb_bus_list.next即是从下一个开始寻找总线,
为什么tmp!=&usb_bus_list呢,可知道在usb_bus_list初始化为该链表头的时候,他的两个成员都是指向它自己吗,
void usb_scan_devices(void)
{
    struct list_head *tmp;

    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;
    }
}
    找到tmp这个指针的地址,然后通过list_entry这个宏找到bus_list这个struct list_head 类型的成员变量,是结构struct usb_bus里面

的,所以我们通过入口取得一个整个的结构.
    如果想对某种类型创建链表,就把一个list_head类型的变量嵌入到该类型中,用list_head中的成员和相对应的处理函数来对链表进行遍

历。如果想得到相应的结构的指针,使用list_entry可以算出来。
/**
 * list_entry - get the struct for this entry
 * @ptr:    the &struct list_head pointer.
 * @type:    the type of the struct this is embedded in.
 * @member:    the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member)
    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
 

阅读(1126) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~