(注:基于三星S5PV210平台,Linux3.0.8内核)
总线:struct bus_type: 描述一个总线对象,完成匹配
struct bus_type {void driver_unregister(struct device_driver *drv)
任务:
1, 构建bus, device, driver
2, 实现匹配方法
3, 实现driver probe
在sys目录下创建文件:/sys/bus/mybus/version
bus_create_file(&mybus,struct bus_attribute * attr)//需要一个struct bus_attribute
可以用以下的宏来构建:
#define __ATTR(_name,_mode,_show,_store) { \
.attr = {.name = __stringify(_name), .mode = _mode },\
.show = _show,\
.store = _store, \
}
#define BUS_ATTR(_name, _mode, _show, _store) \
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
例子:
BUS_ATTR(aaa, 0666, aaa_show, aaa_store);
==>
struct bus_attribute bus_attr_aaa = {
.attr = {.name = __stringify(aaa), .mode = 0666 },
.show = aaa_show,
.store = aaa_store,
}
#define STR(a) #a
STR(ruhua250)==> "ruhua250"
/*mybus.c*/
#include
#include
#include
int mybus_match(struct device *dev, struct device_driver *drv)
{
// 成功返回1, 错误返回0
if(!strncmp(drv->name, dev->kobj.name, strlen(drv->name))){
//表示匹配成功
printk("match ok\n");
return 1;
} else {
return 0; //表示匹配不成功
}
return 0;
}
struct bus_type mybus = {
.name = "mybus",
.match = mybus_match,
};
EXPORT_SYMBOL(mybus);
static int __init mybus_init(void)
{
printk("-------^_* %s-----------\n", __FUNCTION__);
//构建一个总线
int ret;
ret = bus_register(&mybus);
if(ret != 0)
{
printk(KERN_ERR "bus_register error\n");
return ret;
}
return 0;
}
static void __exit mybus_exit(void)
{
printk("-------^_* %s-----------\n", __FUNCTION__);
bus_unregister(&mybus);
}
module_init(mybus_init);
module_exit(mybus_exit);
MODULE_LICENSE("GPL");
/* mydevice.c */
#include
#include
#include
extern struct bus_type mybus;
void mydevice_release(struct device *dev)
{
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
}
struct device mydevice = {
.init_name = "mydevice", /* initial name of the device */
.bus = &mybus, /* type of bus device is on */
.release = mydevice_release
};
static int __init mydevice_init(void)
{
int ret;
/*1.构建一个device 并且注册到总线*/
ret = device_register(&mydevice);
if (ret < 0) {
printk(KERN_ERR "device_register fail\n");
return ret;
}
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
return 0;
}
static void __exit mydevice_exit(void)
{
/*注销device 并且注册到总线*/
device_unregister(&mydevice);
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
}
module_init(mydevice_init);
module_exit(mydevice_exit);
MODULE_LICENSE("GPL");
/* mydriver.c */
#include
#include
#include
extern struct bus_type mybus;
int mydrv_probe(struct device *dev)
{
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
return 0;
}
int mydrv_remove(struct device *dev)
{
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
return 0;
}
struct device_driver mydriver = {
.name = "mydriver",
.bus = &mybus,
.probe = mydrv_probe,
.remove = mydrv_remove
};
static int __init mydriver_init(void)
{
int ret;
/*1.构建一个driver并且注册到总线*/
ret = driver_register(&mydriver);
if (ret < 0) {
printk(KERN_ERR "driver_register fail \n");
return ret;
}
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
return 0;
}
static void __exit mydriver_exit(void)
{
/*注销driver*/
driver_unregister(&mydriver);
printk(KERN_INFO "\n------*_^%s--------\n",__func__);
}
module_init(mydriver_init);
module_exit(mydriver_exit);
MODULE_LICENSE("GPL");
ROOTFS_DIR = /opt/filesystem
MODULE_NAME = mybus
MODULE_NAME2 = mydriver
MODULE_NAME3 = mydevice
ifeq ($(KERNELRELEASE), )
KERNEL_DIR = /home/linux-3.0.8
CUR_DIR = $(shell pwd)
all :
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
cp -raf *.ko $(ROOTFS_DIR)/drv_module
else
obj-m = $(MODULE_NAME).o
obj-m += $(MODULE_NAME2).o
obj-m += $(MODULE_NAME3).o
endif