Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145890
  • 博文数量: 19
  • 博客积分: 1746
  • 博客等级: 上尉
  • 技术积分: 443
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-22 22:54
文章分类
文章存档

2011年(3)

2010年(16)

分类: LINUX

2010-03-07 16:58:51

------------------------------------------------
#个人浅见,如有问题敬请谅解!
#kernel version: 2.6.26
#Author: andy wang
-------------------------------------------------
    在分析完总线和设备的注册以后,再来分析驱动的注册就比较简单了。在注册驱动的时候需要定义驱动关联的总线drv->bus
下面是我的虚拟机usb总线上注册的驱动:
[root@FLYING drivers]# pwd
/sys/bus/usb/drivers
root@FLYING drivers]# tree
.
|-- hiddev
|   |-- bind
|   |-- module -> ../../../../module/usbhid
|   |-- new_id
|   |-- uevent
|   `-- unbind
|-- hub
|   |-- 1-0:1.0 -> ../../../../devices/pci0000:00/0000:00:07.2/usb1/1-0:1.0
|   |-- bind
|   |-- module -> ../../../../module/usbcore
|   |-- new_id
|   |-- uevent
|   `-- unbind
|-- libusual
|   |-- bind
|   |-- module -> ../../../../module/libusual
|   |-- new_id
|   |-- uevent
|   `-- unbind
|-- usb
|   |-- bind
|   |-- uevent
|   |-- unbind
|   `-- usb1 -> ../../../../devices/pci0000:00/0000:00:07.2/usb1
|-- usbfs
|   |-- bind
|   |-- module -> ../../../../module/usbcore
|   |-- new_id
|   |-- uevent
|   `-- unbind
`-- usbhid
    |-- bind
    |-- module -> ../../../../module/usbhid
    |-- new_id
    |-- uevent
`-- unbind
从上面的目录树形图中可以看到注册到usb总线上的设备驱动(红色目录), 以及驱动相关的文件。
 
注册驱动
闲话少说,直接进入主题吧,,,注册驱动调用的函数为driver_register()
217 int driver_register(struct device_driver *drv)
218 {
219         int ret;
220         struct device_driver *other;
221
222         if ((drv->bus->probe && drv->probe) ||
223             (drv->bus->remove && drv->remove) ||
224             (drv->bus->shutdown && drv->shutdown))
225                 printk(KERN_WARNING "Driver '%s' needs updating - please use "
226                         "bus_type methods\n", drv->name);
227
228         other = driver_find(drv->name, drv->bus);
229         if (other) {
230                 put_driver(other);
231                 printk(KERN_ERR "Error: Driver '%s' is already registered, "
232                         "aborting...\n", drv->name);
233                 return -EEXIST;
234         }
235
236         ret = bus_add_driver(drv);
237         if (ret)
238                 return ret;
239         ret = driver_add_groups(drv, drv->groups);
240         if (ret)
241                 bus_remove_driver(drv);
242         return ret;
243 }
 
221-224,一般不需要同时定义busdrvprob,remove,shutdown方法的。
228, 遍历drv->bus下面的驱动,查找判断该驱动是否已经注册.如果已经注册了,那肯定就不能够再注册了撒。
236, bus_add_driver()就是把设备驱动注册到关联的总线上了,其实这个和注册设备流程都是差不多的.
跟踪一下bus_add_driver()代码流程:
bus_add_driver()->bus_get()->kobject_init_and_add()->driver_attach()->driver_create_file()->driver_add_attrs()->add_bind_files()->kobject_uevent();
 
下面看看bus_add_driver()的代码:
644 int bus_add_driver(struct device_driver *drv)
645 {
646         struct bus_type *bus;
647         struct driver_private *priv;
648         int error = 0;
649
650         bus = bus_get(drv->bus);
651         if (!bus)
652                 return -EINVAL;
653
654         pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
655
656         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
657         if (!priv) {
658                 error = -ENOMEM;
659                 goto out_put_bus;
660         }
661         klist_init(&priv->klist_devices, NULL, NULL);
662         priv->driver = drv;
663         drv->p = priv;
664         priv->kobj.kset = bus->p->drivers_kset;
665         error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
666                                      "%s", drv->name);
667         if (error)
668                 goto out_unregister;
664         priv->kobj.kset = bus->p->drivers_kset;
665         error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
666                                      "%s", drv->name);
667         if (error)
668                 goto out_unregister;
669
670         if (drv->bus->p->drivers_autoprobe) {
671                 error = driver_attach(drv);
672                 if (error)
673                         goto out_unregister;
674         }
675         klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
676         module_add_driver(drv->owner, drv);
677
678         error = driver_create_file(drv, &driver_attr_uevent);
679         if (error) {
680                 printk(KERN_ERR "%s: uevent attr (%s) failed\n",
681                         __func__, drv->name);
682         }
683         error = driver_add_attrs(bus, drv);
684         if (error) {
685                 /* How the hell do we get out of this pickle? Give up */
686                 printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
687                         __func__, drv->name);
688         }
689         error = add_bind_files(drv);
690         if (error) {
691                 /* Ditto */
692                 printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
693                         __func__, drv->name);
694         }
695
696         kobject_uevent(&priv->kobj, KOBJ_ADD);
697         return error;
                      …………………
}
 
650行,取出驱动所在的总线。
656行,动态分配driver_private结构,其实这个和以前讲过的总线注册bus_type_private结构相似,可以对照着比较一下。
665行,注册驱动kobj(priv->kobj),在这里我们看到parentNULL,那么我们注册的这个kobj将会在什么地方建立目录呢?答案就在664行代码priv->kobj.kset = bus->p->drivers_kset ,从这里可以看出,我们注册的驱动会在/sys/bus/xxx/driver下建立目录。
这里还有一个要注意的地方就是这里定义的ktypedriver_ktype ,在driver_ktype中定义了驱动属性文件的读写方法,在稍候分析驱动属性文件读写时会看到。
671行,匹配已经注册到总线上的设备;这个函数与注册设备时匹配总线上驱动是一样的,在以前已经仔细分析过这个函数的匹配过程了。
678-689行,这几个函数其实就是创建设备文件了,实现比较简单。
696行,通知用户层的udev KOBJ_ADD事件发生。
 
到这里驱动就成功注册到总线上了。
 
驱动属性文件读写
接下来还是来看一下驱动目录下面的文件是如何读写的:
要研究它首先得需要找到驱动目录kobj定义的ktype,在注册驱动的时候已经看到了这个ktypedriver_ktype,那就先来看看它的定义:
static struct kobj_type driver_ktype = {
         .sysfs_ops = &driver_sysfs_ops,
         .release       = driver_release,
};
static struct sysfs_ops driver_sysfs_ops = {
         .show         = drv_attr_show,
         .store          = drv_attr_store,
};
static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr,
                                  const char *buf, size_t count)
{
         struct driver_attribute *drv_attr = to_drv_attr(attr);
         struct driver_private *drv_priv = to_driver(kobj);
         ssize_t ret = -EIO;
 
         if (drv_attr->store)
                   ret = drv_attr->store(drv_priv->driver, buf, count);
         return ret;
}
可见驱动目录下面的文件写方法最终调用的是drv_attr->store();
 
我们这里还是uevent驱动属性文件为例,先看看它的定义:
static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
#define DRIVER_ATTR(_name, _mode, _show, _store)   \
struct driver_attribute driver_attr_##_name =           \
         __ATTR(_name, _mode, _show, _store)
static ssize_t driver_uevent_store(struct device_driver *drv,
                                        const char *buf, size_t count)
{
         enum kobject_action action;
 
         if (kobject_action_type(buf, count, &action) == 0)
                   kobject_uevent(&drv->p->kobj, action);
         return count;
}
定义和实现还是比较简单的,uevent是一个只写文件,所以在写这个文件时会调用函数driver_uevent_store(),发送相关事件给udev
 
阅读(3011) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~