Linux驱动2_总线设备(一)

来源:互联网 发布:阿里云cdn加速设置 编辑:程序博客网 时间:2024/06/10 08:52

//参考Linux设备驱动程序(lld3)//实现一个简单的虚拟总线 simple bus//simple_bus_type为总线类型//simple_bus为总线设备////simple.c 实现#include "simple.h"//增加设备引用计数static struct simple_device *simple_dev_get(struct simple_device *dev){if (dev)get_device(&dev->device);return dev;}//递减设备引用计数static void simple_dev_put(struct simple_device *dev){if (dev)put_device(&dev->device);}//匹配设备/驱动//当有新设备或新驱动添加到总线时,判断是否匹配//调用路径:核心设备子系统->static int simple_device_match(struct device *dev, struct device_driver *drv){struct simple_device *sim_dev = to_simple_device(dev);struct simple_driver *sim_drv = to_simple_driver(drv);struct simple_class_id *ids = sim_drv->classes;if (ids)while (ids->class_id != SIMPLE_CLASS_END){if (ids->class_id == sim_dev->class_id.class_id)return 1;ids++;}return 0;}//添加设备/驱动//当simple_device_match返回true,说明device和driver匹配,通过//调用probe调用驱动的probe函数,初始化设备//调用路径:核心设备子系统->static int simple_device_probe(struct device *dev){int ret = 0;struct simple_device *sim_dev;struct simple_driver *sim_drv;sim_dev = to_simple_device(dev);sim_drv = to_simple_driver(dev->driver);simple_dev_get(sim_dev);if (sim_drv->probe)ret = sim_drv->probe(sim_dev);if (ret)simple_dev_put(sim_dev);return ret;}//热插拔设备//总线上设备被热插拔//调用路径:核心设备子系统->static int simple_device_remove(struct device *dev){struct simple_device *sim_dev = to_simple_device(dev);struct simple_driver *sim_drv = to_simple_driver(dev->driver);if (sim_drv){if (sim_drv->remove){sim_drv->remove(sim_dev);}}simple_dev_put(sim_dev);return 0;}//获取设备class idstatic ssize_t simple_device_show_class_id(struct device *dev, struct device_attribute *attr, char *buf){struct simple_device *sim_dev = to_simple_device(dev);sprintf(buf, "0x%x\n", sim_dev->class_id.class_id);return strlen(buf) + 1;}//simple bus 设备属性struct device_attribute simple_device_attrs[] = {__ATTR(class_id, S_IRUGO, simple_device_show_class_id, NULL),__ATTR_NULL};//simple bus 总线类型struct bus_type simple_bus_type = {.name = "simple",.match = simple_device_match,.probe = simple_device_probe,.remove = simple_device_remove,.dev_attrs = simple_device_attrs };static void simple_bus_release(struct device *dev){return;}//simple bus 总线设备struct simple_bus simple_bus;//simple bus 模块初始化static int __init simple_init(void){    int ret;    /* create /sys/bus/simple.*/    if ((ret = bus_register(&simple_bus_type)) < 0)    {    printk(KERN_ALERT "[SIMPLE] bus_register failed.\n");    goto err_bus_register;    }    simple_bus.dev.release = simple_bus_release;    //simple_bus.dev.parent为null,表示为该总线的顶层设备    dev_set_name(&simple_bus.dev, "simple");    /* create /sys/devices/simple.*/    if ((ret = device_register(&simple_bus.dev)))    {    printk(KERN_ALERT "[SIMPLE] device_register failed.\n");    goto err_dev_register;    }    return ret;err_dev_register:bus_unregister(&simple_bus_type);err_bus_register:return ret;}//simple bus 模块卸载static void __exit simple_exit(void){device_unregister(&simple_bus.dev);bus_unregister(&simple_bus_type);}static void simple_device_release(struct device *dev){return;}//注册设备//向simple bus注册设备int simple_register_device(struct simple_device *dev){dev_set_name(&dev->device, dev->name);//设备类型为实现的simple_bus_typedev->device.bus = &simple_bus_type;//挂载的总线为simple_busdev->device.parent = &simple_bus.dev; dev->device.release = simple_device_release;return device_register(&dev->device);}EXPORT_SYMBOL(simple_register_device);//注销设备//从simple bus注销设备void simple_unregister_device(struct simple_device *dev){/*  *device_unregister will do in two parts, first, remove it from all the subsystems with device_del(),  *then decrement the reference count via put_device(). If that is the final reference count, *the device will be cleaned up via device_release() above. Otherwise, the structure will stick  *around until the final reference to the device is dropped. */device_unregister(&dev->device);} EXPORT_SYMBOL(simple_unregister_device);//注册驱动//向simple bus注册驱动int simple_register_driver(struct simple_driver *drv){int ret = 0;drv->driver.name= drv->name;drv->driver.bus = &simple_bus_type;ret = driver_register(&drv->driver);return ret;}EXPORT_SYMBOL(simple_register_driver);//注销驱动//从simple bus注销驱动void simple_unregister_driver(struct simple_driver *drv){driver_unregister(&drv->driver);}EXPORT_SYMBOL(simple_unregister_driver);module_init(simple_init);module_exit(simple_exit);MODULE_LICENSE("GPL");

//simple.h,类型声明#include <linux/init.h>#include <linux/module.h>#include <linux/device.h>#ifndef _SIMPLE_BUS_H_#define _SIMPLE_BUS_H_#define to_simple_device(dev) container_of(dev, struct simple_device, device)#define to_simple_driver(drv) container_of(drv, struct simple_driver, driver)#define SIMPLE_CLASS_END  0xffffstruct simple_class_id{u16 class_id;};struct simple_device{char *name;struct device device;struct simple_class_id class_id;};struct simple_driver{char *name;struct device_driver driver;struct simple_class_id *classes;int (*probe) (struct simple_device *dev);/*Device removed (NULL if not a hot-plug capable driver) */int (*remove) (struct simple_device *dev);};struct simple_bus{struct device dev;};extern int simple_register_device(struct simple_device *dev);extern void simple_unregister_device(struct simple_device *dev);extern int simple_register_driver(struct simple_driver *drv);extern void simple_unregister_driver(struct simple_driver *drv);#endif





1 0
原创粉丝点击