1、在/sys/bus下注册一个自定义总线
#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/kobject.h>
#include<linux/slab.h>
#include<linux/sysfs.h>
#include<linux/device.h>
#include "my_bus.h"
#if 0
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
struct device_attribute *dev_attrs; /* use dev_groups instead */
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
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 (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
const struct iommu_ops *iommu_ops;
struct subsys_private *p;
struct lock_class_key lock_key;
};
int bus_register(struct bus_type *bus)
#endif
struct bus_type my_bus = {
.name = "my_bus",
.match = my_bus_match,
.probe = my_bus_probe,
};
int my_bus_match(struct device *dev, struct device_driver *drv)
{
return (strcmp(dev_name(dev),drv->name) == 0);
}
int my_bus_probe(struct device *dev)
{
struct device_driver *drv = dev->driver;
if(drv->probe)
drv->probe(dev);
return 0;
}
static int my_bus_init(void)
{
int ret;
ret = bus_register(&my_bus);
return ret;
}
static void my_bus_exit(void)
{
bus_unregister(&my_bus);
}
module_init(my_bus_init);
module_exit(my_bus_exit);
MODULE_LICENSE("GPL");
//my_bus.h
#ifndef _ATTR_H_
#define _ATTR_H_
int my_bus_match(struct device *dev, struct device_driver *drv);
int my_bus_probe(struct device *dev);
#endif
2、在总线目录下创建自己的属性文件
#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/kobject.h>
#include<linux/slab.h>
#include<linux/sysfs.h>
#include<linux/device.h>
#include "my_bus.h"
#if 0
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
struct device_attribute *dev_attrs; /* use dev_groups instead */
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
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 (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
const struct iommu_ops *iommu_ops;
struct subsys_private *p;
struct lock_class_key lock_key;
};
int bus_register(struct bus_type *bus)
static struct bus_attribute bus_attr_uevent = __ATTR(uevent, S_IWUSR, NULL,
bus_uevent_store);
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
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);
};
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
#endif
struct bus_type my_bus = {
.name = "my_bus",
.match = my_bus_match,
.probe = my_bus_probe,
};
static struct bus_attribute my_bus_attr = __ATTR(attr1, 0660, my_bus_attr_show,my_bus_attr_store);
ssize_t my_bus_attr_show(struct bus_type *bus, char *buf)
{
ssize_t ret;
ret = sprintf(buf,"this is in my_bus_attr_show\n");
return ret;
}
ssize_t my_bus_attr_store(struct bus_type *bus, const char *buf, size_t count)
{
printk("my_bus_attr_store:buf = %s\n",buf);
return count;
}
int my_bus_match(struct device *dev, struct device_driver *drv)
{
return (strcmp(dev_name(dev),drv->name) == 0);
}
int my_bus_probe(struct device *dev)
{
struct device_driver *drv = dev->driver;
if(drv->probe)
drv->probe(dev);
return 0;
}
static int my_bus_init(void)
{
int ret;
ret = bus_register(&my_bus);
ret = bus_create_file(&my_bus, &my_bus_attr);
return ret;
}
static void my_bus_exit(void)
{
bus_remove_file(&my_bus, &my_bus_attr);
bus_unregister(&my_bus);
}
module_init(my_bus_init);
module_exit(my_bus_exit);
MODULE_LICENSE("GPL");
#ifndef _ATTR_H_
#define _ATTR_H_
int my_bus_match(struct device *dev, struct device_driver *drv);
int my_bus_probe(struct device *dev);
ssize_t my_bus_attr_show(struct bus_type *bus, char *buf);
ssize_t my_bus_attr_store(struct bus_type *bus, const char *buf, size_t count);
#endif
3、一些结构体和api介绍
3.1 struct bus_type
The bus type of the device
3.2 bus_register
注册一个总线
3.3 bus_unregister
去除一个总线
3.4 bus_create_file
总线目录下创建属性文件api