📄 lddbus.c
字号:
/* * A virtual bus for LDD sample code devices to plug into. This * code is heavily borrowed from drivers/base/sys.c * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files. The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates. No warranty is attached; * we cannot take responsibility for errors or fitness for use. * *//* $Id: lddbus.c,v 1.9 2004/09/26 08:12:27 gregkh Exp $ */#include <linux/device.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/string.h>#include "lddbus.h"MODULE_AUTHOR("Jonathan Corbet");MODULE_LICENSE("Dual BSD/GPL");static char *Version = "$Revision: 1.9 $";/* * Respond to hotplug events. */static int ldd_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size){ envp[0] = buffer; if (snprintf(buffer, buffer_size, "LDDBUS_VERSION=%s", Version) >= buffer_size) return -ENOMEM; envp[1] = NULL; return 0;}/* * Match LDD devices to drivers. Just do a simple name test. */static int ldd_match(struct device *dev, struct device_driver *driver){ return !strncmp(dev->bus_id, driver->name, strlen(driver->name));}/* * The LDD bus device. */static void ldd_bus_release(struct device *dev){ printk(KERN_DEBUG "lddbus release\n");} struct device ldd_bus = { .bus_id = "ldd0", .release = ldd_bus_release};/* * And the bus type. */struct bus_type ldd_bus_type = { .name = "ldd", .match = ldd_match, .hotplug = ldd_hotplug,};/* * Export a simple attribute. */static ssize_t show_bus_version(struct bus_type *bus, char *buf){ return snprintf(buf, PAGE_SIZE, "%s\n", Version);}static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);/* * LDD devices. *//* * For now, no references to LDDbus devices go out which are not * tracked via the module reference count, so we use a no-op * release function. */static void ldd_dev_release(struct device *dev){ }int register_ldd_device(struct ldd_device *ldddev){ ldddev->dev.bus = &ldd_bus_type; ldddev->dev.parent = &ldd_bus; ldddev->dev.release = ldd_dev_release; strncpy(ldddev->dev.bus_id, ldddev->name, BUS_ID_SIZE); return device_register(&ldddev->dev);}EXPORT_SYMBOL(register_ldd_device);void unregister_ldd_device(struct ldd_device *ldddev){ device_unregister(&ldddev->dev);}EXPORT_SYMBOL(unregister_ldd_device);/* * Crude driver interface. */static ssize_t show_version(struct device_driver *driver, char *buf){ struct ldd_driver *ldriver = to_ldd_driver(driver); sprintf(buf, "%s\n", ldriver->version); return strlen(buf);} int register_ldd_driver(struct ldd_driver *driver){ int ret; driver->driver.bus = &ldd_bus_type; ret = driver_register(&driver->driver); if (ret) return ret; driver->version_attr.attr.name = "version"; driver->version_attr.attr.owner = driver->module; driver->version_attr.attr.mode = S_IRUGO; driver->version_attr.show = show_version; driver->version_attr.store = NULL; return driver_create_file(&driver->driver, &driver->version_attr);}void unregister_ldd_driver(struct ldd_driver *driver){ driver_unregister(&driver->driver);}EXPORT_SYMBOL(register_ldd_driver);EXPORT_SYMBOL(unregister_ldd_driver);static int __init ldd_bus_init(void){ int ret; ret = bus_register(&ldd_bus_type); if (ret) return ret; if (bus_create_file(&ldd_bus_type, &bus_attr_version)) printk(KERN_NOTICE "Unable to create version attribute\n"); ret = device_register(&ldd_bus); if (ret) printk(KERN_NOTICE "Unable to register ldd0\n"); return ret;}static void ldd_bus_exit(void){ device_unregister(&ldd_bus); bus_unregister(&ldd_bus_type);}module_init(ldd_bus_init);module_exit(ldd_bus_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -