1, 构建bus, device, driver
2, 实现匹配方法
3, 实现driver probe
/* mybus.c */
#include
#include
#include
#include "desc.h"
char bus_version[128] = "bus verison v1";
int mybus_match(struct device *dev, struct device_driver *drv)
{
/*匹配成功返回1,失败返回0*/
if (!strncmp(drv->name, dev->kobj.name, strlen(drv->name))) {
printk("mybus_match ok !\n");
return 1;
} else {
//表示匹配不成功
return 0;
}
}
// /sys/bus/mybus/version
// cat version -->verison_show()
// echo "xxx" > version 会调用version_store()
ssize_t version_show(struct bus_type *bus, char *buf)
{
printk("-------^_* %s-----------\n", __FUNCTION__);
return snprintf(buf, 128,"%s-%d-%c", bus_version, 88, 'A');
}
ssize_t version_store(struct bus_type *bus, const char *buf, size_t count)
{
printk("-------^_* %s-----------\n", __FUNCTION__);
return snprintf(bus_version,128, "%s", buf);
}
/*
#define BUS_ATTR(_name, _mode, _show, _store) \
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
*/
//实际是一个结构体---struct bus_attribute bus_attr_version
BUS_ATTR(version,0666, version_show, version_store);
struct bus_type mybus = {
.name = "mybus",
.match = mybus_match
};
static int __init mybus_init(void)
{
int ret;
/*1.构建一个总线mybus*/
ret = bus_register(&mybus);
if (ret < 0) {
printk(KERN_ERR "bus_register fail\n");
return ret;
}
// 可以在/sys/bus/mybus/创建文件 version
ret = bus_create_file(&mybus, &bus_attr_version);
if (ret < 0) {
printk(KERN_ERR "bus_create_file fail\n");
bus_unregister(&mybus);
return ret;
}
printk("------*_^ %s--------\n",__FUNCTION__);
return 0;
}
static void __exit mybus_exit(void)
{
/*注销总线mybus*/
bus_unregister(&mybus);
printk(KERN_INFO "------*_^ %s--------\n",__FUNCTION__);
}
EXPORT_SYMBOL(mybus);
module_init(mybus_init);
module_exit(mybus_exit);
MODULE_LICENSE("GPL");
/* mydevice.c */
#include
#include
#include
#include "desc.h"
extern struct bus_type mybus;
void mydevice_release(struct device *dev)
{
printk(KERN_INFO "------*_^ %s--------\n",__FUNCTION__);
}
/*表示一个特定的设备信息*/
struct dev_desc info = {
.name = "simple device",
.irqno = 1212,
.addr = 0x12121212,
//...FIXME...
};
struct device mydevice = {
.init_name = "match", /* initial name of the device 跟device的符号相同才能通过bus匹配成功*/
.bus = &mybus, /* type of bus device is on */
.release = mydevice_release,
.platform_data = &info /* Platform specific data, device*/
};
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 "------*_^%s--------\n",__FUNCTION__);
return 0;
}
static void __exit mydevice_exit(void)
{
/*注销device 并且注册到总线*/
device_unregister(&mydevice);
printk(KERN_INFO "------*_^%s--------\n",__FUNCTION__);
}
module_init(mydevice_init);
module_exit(mydevice_exit);
MODULE_LICENSE("GPL");
/* mydriver.c */
#include
#include
#include
#include "desc.h"
extern struct bus_type mybus;
int mydrv_probe(struct device *dev)
{
printk("------*_^%s--------\n",__FUNCTION__);
/*获取到device中信息*/
struct dev_desc * p = (struct dev_desc *)dev->platform_data;
printk("name = %s\n", p->name);
printk("irq = %d\n", p->irqno);
printk("addr = 0x%x\n", p->addr);
return 0;
}
int mydrv_remove(struct device *dev)
{
printk("------*_^%s--------\n",__FUNCTION__);
return 0;
}
struct device_driver mydriver = {
.name = "match", /*跟device的符号相同才能通过bus匹配成功*/
.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("------*_^%s--------\n",__FUNCTION__);
return 0;
}
static void __exit mydriver_exit(void)
{
/*注销driver*/
driver_unregister(&mydriver);
printk("------*_^%s--------\n",__FUNCTION__);
}
module_init(mydriver_init);
module_exit(mydriver_exit);
MODULE_LICENSE("GPL");
/* desc.h */
#ifndef __DESC_H__
#define __DESC_H__
//设计一个对象
struct dev_desc{
char *name;
int irqno;
unsigned long addr;
};
#endif
# Makefile
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