设备驱动模型:总线bus_type 设备device 驱动driver

一.总线 bus_type
数据结构
struct bus_type{
const char *name; //总线类型的名称
struct bus_attribute *bus_attrs;
struct device_attribute *dev_atrrs;
struct driver_attribute *drv_attrs;

int (*match) (struct device *dev,struct device_driver *drv); //设备驱动匹配方法
int (*uevent)(struct device *dev,struct kobj_uevent_env *env); //热插拔时,内核向用户传递参数
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(*suspend_late)(struct device *dev,pm_message_t state);//挂起函数
int(*resume_early)(struct device *dev);//唤醒函数
int(*resume)(struct device *dev);//恢复供电状态使得设备正常工作
struct dev_pm_ops *pm;
struct bus_type_private *p;
}

总线结构中常用的是name,match,probe其他都是使用系统默认。

注册总线
int bus_register(struct bus_type *bus);

删除总线
void bus_unregiser(struct bus_type *bus);

总线的属性
struct bus_attribute{
struct attribute attr; //总线的属性
ssize_t (*show)(struct bus_type *bus,char *buf); //属性读函数
ssize_t (*store)(struct bus_type *bus,const char *buf,size_t count); //总线写函数
}

初始化属性
BUS_ATTTR(_name,_mode,_show,_store)
属性名称 权限 读函数 写函数

也可以使用下面方式定义
struct bus_attribute bus_attr={
.attr = {.name = config, .mode = 0644};
.show = bus_show, //自定义的show函数
.store = bus_store, //自定义的store函数
}

创建总线属性
int bus_create_file(struct bus_type *bus,struct bus_attribute *attr);
删除总线属性
void bus_remove_file(struct bus_type *bus,struct bus_attribute *attr);

简单测试
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>

MODULE_LICENSE("GPL");

struct bus_type mybus={

.name = "mybus"

};

ssize_t bus_show(struct bus_type *bus,char *buf)
{
return 0;
}

ssize_t bus_store(struct bus_type *bus,const char *buf,size_t count)
{
return 0;
}

struct bus_attribute attr={
.attr = {
.name = "config",
.mode = 0644,
},
.show = bus_show,
.store = bus_store,
};

int __init bus_init(void)
{
int ret;
ret = bus_register(&mybus);
if(ret)
{
printk(KERN_WARNING"bus register failed!\n");
return ret;
}

bus_create_file(&mybus,&attr);

printk(KERN_INFO"bus init!\n");

return 0;
}

void __exit bus_exit(void)
{
bus_unregister(&mybus);
bus_remove_file(&mybus,&attr);
return;
}

module_init(bus_init);
module_exit(bus_exit);

二.设备 device
设备结构
struct device {
struct klist klist_children; //连接子设备的链表
struct device *parent; //指向父设备的指针
struct kobject kobj;//内嵌的kobject结构体
char bus_id[BUS_ID_SIZE];//连接到总线上的位置
unsigned uevent_suppress:1;//是否支持热插拔事件
const char *init_name; //设备的初始化名字
struct device_type *type;//设备的相关的特殊处理函数
struct bus_type *bus;//指向连接的总线指针
struct device_driver *driver;//指向该设备的驱动程序
void *driver_data; //指向驱动程序私有数据的指针
struct dev_pm_info power; //电源管理信息
dev_t devt;//设备号
struct class *class; //指向设备所属类
struct attribute_group **groups;//设备的组属性
void (*release)(struct device *dev);//释放设备描述符的回调函数
...
}
上面属性中必须要的是:bus_id parent release


注册设备
int device_register(struct device *dev);

注销设备
int device_unregister(struct device *dev);

设备属性
struct device_attribute{
struct attribute attr; //属性
ssize_t (*show)(struct device *dev,struct device_attribute *attr,char *buf); //显示属性的方法,读函数
ssize_t (*store)(struct device *dev,struct device_attribute *attr,const char *buf,size_t count);//设置设备的属性 ,写函数
}

定义属性
DEVICE_ATTR(_name,_mode,_show,_store);
也可以使用下面方法设置
struct device_attribute attr={
.attr = {
.name = "test_device",
.mode = 0644
},
.show = device_show,
.store = device_store,
};

添加设备
int device_create_file(struct device *device,struct device_attribute *entry);
删除设备
void device_remove_file(struct device *device,struct device_attribute *attr);
简单测试
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>

MODULE_LICENSE("GPL");
void device_release(struct device *dev)
{
printk(KERN_INFO"release device!\n");
}

ssize_t device_show(struct device *dev,struct device_attribute *attr,char *buf)
{
ssize_t ret = 0 ;

return ret;
}

ssize_t device_store(struct device *dev,struct device_attribute *attr,const char *buf,size_t count)
{
ssize_t ret = 0;

return ret;
}

struct device dev={
//.bus_id = "test_device",
.parent = NULL,
.release = device_release,
};

struct device_attribute attr={

.attr={
.name = "dev",
.mode = 0644,
},
.show = device_show,
.store = device_store,
};


int __init device_init(void)
{
int ret;
ret = device_register(&dev);
if(ret)
{
printk(KERN_WARNING"register device failed!\n");
return ret;
}

device_create_file(&dev,&attr);

printk("init device!\n");

return 0;
}

void __exit device_exit(void)
{
device_unregister(&dev);

device_remove_file(&dev,&attr);
return;
}

module_init(device_init);
module_exit(device_exit);

三. 驱动
驱动结构
struct device_driver{
const char *name; //设备驱动程序的名字
struct bus_type *bus;//指向驱动所属的总线,总线上有很多设备
struct module owner;//设备驱动自身模块
const char *mod_name;//驱动模块名字
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);//设备恢复状态时调用的方法
struct attribute_group **groups; //属性组
struct dev_pm_ops *pm; //用于电源管理
struct driver_private *p; //设备驱动私有数据

}


驱动注册
int driver_register(struct device_driver *drv);
驱动注销
void driver_unregister(struct device_driver *drv);

驱动属性
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);
};

创建属性文件
int driver_create_file(struct device_driver *drv,struct driver_attribute *attr);

移除属性文件
void driver_remove_file(struct device_driver *drv,struct driver_attribute *attr);


总结:
总线,设备,驱动三者编写的形式上是非常相近的

注册
xx_register
注销
xx_unregister

属性
struct xx_attribute{
struct attribute attr;
ssize_t (*show)(...)
ssize_t (*store)(...)
};

创建属性文件
xx_create_file
移除属性文件
xx_remove_file



















  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值