您的位置:首页 > 运维架构 > Linux

Linux驱动之设备模型(6)

2013-04-23 09:04 411 查看

原文地址: /article/7669646.html

7.设备驱动

7.1 设备驱动

l 在Linux设备模型中,设备驱动用device_driver结构来表示

struct device_driver {

constchar *name;

structbus_type *bus;

structmodule *owner;

const structof_device_id *of_match_table;

int (*probe) (struct device *dev);

int (*remove) (struct device *dev);

void (*shutdown) (struct device *dev);

int (*suspend) (struct device *dev,pm_message_t state);

int (*resume) (struct device *dev);
const struct attribute_group **groups;

const struct dev_pm_ops *pm;

struct driver_private*p;

};

7.2 驱动属性

l 驱动属性由driver_attribute来表示

struct driver_attribute {

struct attribute attr;

ssize_t (*show)(struct device_driver*driver, char *buf);

ssize_t (*store)(struct device_driver*driver, const char *buf,

size_t count);

};

DRIVER_ATTR(_name,_mode, _show, _store)

l 属性操作

n 创建属性

int driver_create_file(struct device_driver *driver,

const structdriver_attribute *attr);

n 删除属性

void driver_remove_file(struct device_driver*driver,

const structdriver_attribute *attr);

7.3 驱动基本操作

l 驱动注册和注销

intdriver_register(struct device_driver *drv)

voiddriver_unregister(struct device_driver *drv)

l 驱动注册分析

n driver_register

int driver_register(struct device_driver *drv)

{

int ret;

struct device_driver *other;

BUG_ON(!drv->bus->p);

if ((drv->bus->probe&&drv->probe) ||

(drv->bus->remove&& drv->remove)||

(drv->bus->shutdown&&drv->shutdown))

printk(KERN_WARNING "Driver '%s' needs updating -please use "

"bus_type methods\n", drv->name);

other =driver_find(drv->name,drv->bus);

if (other) {

put_driver(other);

}

ret = bus_add_driver(drv);

ret= driver_add_groups(drv, drv->groups);

}

n bus_add_driver

int bus_add_driver(struct device_driver *drv)

{

bus = bus_get(drv->bus);

error=kobject_init_and_add(&priv->kobj,&driver_ktype, NULL,

"%s", drv->name);

if(drv->bus->p->drivers_autoprobe){
error = driver_attach(drv);

}

klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers);

error =driver_create_file(drv,&driver_attr_uevent);

error = driver_add_attrs(bus, drv);

kobject_uevent(&priv->kobj,KOBJ_ADD);

}

n driver_attach

int driver_attach(struct device_driver *drv)

{

return bus_for_each_dev(drv->bus,NULL, drv,__driver_attach);

}
遍历总线上的所有设备,当有驱动支持的设备时,调用__driver_attach函数完成相应的工作__driver_attach()->driver_probe_device()->driver_probe_device()->bus->probe()->
drv->probe ()优先调用总线中定义的probe函数,如果bus中未定义probe,则再调用驱动中定义的probe。

7.4 实例分析

#include

#include

#include

#include

#include

extern struct bus_type scbus_type;

static char * Version = "revision1.0,scdriver";

static int sc_probe(struct device *dev)

{

printk("driver found device\n");

return 0;

}

static int sc_remove(struct device *dev)

{

printk("device remove \n");

return 0;

}

struct device_driver scdriver = {
.name = "scdevice0",

.bus =&scbus_type,
.probe =sc_probe,
.remove =sc_remove,

};

static ssize_t driver_show_version(struct device_driver *driver, char *buf)

{

return sprintf(buf, "%s\n", Version);

}

static DRIVER_ATTR(version, S_IRUGO,driver_show_version, NULL);

static int __initscdriver_init(void)

{

int ret;

ret= driver_register(&scdriver);

if(ret)

return ret;

ret= driver_create_file(&scdriver,&driver_attr_version);

if(ret)

goto err_create;

printk("drvierregistered\n");

return 0;

err_create:

driver_unregister(&scdriver);

return ret;

}

static void __exit scdriver_exit(void)

{

driver_remove_file(&scdriver,&driver_attr_version);

driver_unregister(&scdriver);

}

module_init(scdriver_init);

module_exit(scdriver_exit);

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("CJOK");

试验结果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: