1 /*
2 * A virtual bus for LDD sample code devices to plug into. This
3 * code is heavily borrowed from drivers/base/sys.c
4 *
5 * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
6 * Copyright (C) 2001 O'Reilly & Associates
7 *
8 * The source code in this file can be freely used, adapted,
9 * and redistributed in source or binary form, so long as an
10 * acknowledgment appears in derived source files. The citation
11 * should list that the code comes from the book "Linux Device
12 * Drivers" by Alessandro Rubini and Jonathan Corbet, published
13 * by O'Reilly & Associates. No warranty is attached;
14 * we cannot take responsibility for errors or fitness for use.
15 *
16 */
17 /* $Id: lddbus.c,v 1.9 2004/09/26 08:12:27 gregkh Exp $ */
18
19 #include <linux/device.h>
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <linux/string.h>
24 #include "lddbus.h"
25
26 MODULE_AUTHOR("Jonathan Corbet");
27 MODULE_LICENSE("Dual BSD/GPL");
28 static char *Version = "$Revision: 1.9 $";
29
30 /*
31 * Respond to hotplug events.
32 */
33
34 /*
35 * It seems that struct bus_type has changed a lot.
36 * Gone: hotplug
37 * New: uevent, probe, remove, suspend_late, resume_early, shutdown
38 * I've only put in the uevent handler, since it is not clear to me
39 * what functionality an "ldd" device should provide for the others.
40 */
41
42 static int ldd_uevent(struct device *dev, struct kobj_uevent_env *env) {
43 if (add_uevent_var (env, "LDDVUS_VERSION=%s", Version))
44 return -ENOMEM;
45 return 0;
46 };
47
48 /*
49 * Match LDD devices to drivers. Just do a simple name test.
50 */
51 static int ldd_match(struct device *dev, struct device_driver *driver)
52 {
53 return !strncmp(dev->bus_id, driver->name, strlen(driver->name));
54 }
55
56
57 /*
58 * The LDD bus device.
59 */
60 static void ldd_bus_release(struct device *dev)
61 {
62 printk(KERN_DEBUG "lddbus release\n");
63 }
64
65 struct device ldd_bus = {
66 .bus_id = "ldd0",
67 .release = ldd_bus_release
68 };
69
70
71 /*
72 * And the bus type.
73 */
74 struct bus_type ldd_bus_type = {
75 .name = "ldd",
76 .match = ldd_match,
77 .uevent = ldd_uevent,
78 };
79
80 /*
81 * Export a simple attribute.
82 */
83 static ssize_t show_bus_version(struct bus_type *bus, char *buf)
84 {
85 return snprintf(buf, PAGE_SIZE, "%s\n", Version);
86 }
87
88 static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
89
90
91
92 /*
93 * LDD devices.
94 */
95
96 /*
97 * For now, no references to LDDbus devices go out which are not
98 * tracked via the module reference count, so we use a no-op
99 * release function.
100 */
101 static void ldd_dev_release(struct device *dev)
102 { }
103
104 int register_ldd_device(struct ldd_device *ldddev)
105 {
106 ldddev->dev.bus = &ldd_bus_type;
107 ldddev->dev.parent = &ldd_bus;
108 ldddev->dev.release = ldd_dev_release;
109 strncpy(ldddev->dev.bus_id, ldddev->name, BUS_ID_SIZE);
110 return device_register(&ldddev->dev);
111 }
112 EXPORT_SYMBOL(register_ldd_device);
113
114 void unregister_ldd_device(struct ldd_device *ldddev)
115 {
116 device_unregister(&ldddev->dev);
117 }
118 EXPORT_SYMBOL(unregister_ldd_device);
119
120 /*
121 * Crude driver interface.
122 */
123
124
125 static ssize_t show_version(struct device_driver *driver, char *buf)
126 {
127 struct ldd_driver *ldriver = to_ldd_driver(driver);
128
129 sprintf(buf, "%s\n", ldriver->version);
130 return strlen(buf);
131 }
132
133
134 int register_ldd_driver(struct ldd_driver *driver)
135 {
136 int ret;
137
138 driver->driver.bus = &ldd_bus_type;
139 ret = driver_register(&driver->driver);
140 if (ret)
141 return ret;
142 driver->version_attr.attr.name = "version";
143 driver->version_attr.attr.owner = driver->module;
144 driver->version_attr.attr.mode = S_IRUGO;
145 driver->version_attr.show = show_version;
146 driver->version_attr.store = NULL;
147 return driver_create_file(&driver->driver, &driver->version_attr);
148 }
149
150 void unregister_ldd_driver(struct ldd_driver *driver)
151 {
152 driver_unregister(&driver->driver);
153 }
154 EXPORT_SYMBOL(register_ldd_driver);
155 EXPORT_SYMBOL(unregister_ldd_driver);
156
157
158
159 static int __init ldd_bus_init(void)
160 {
161 int ret;
162
163 ret = bus_register(&ldd_bus_type);
164 if (ret)
165 return ret;
166 if (bus_create_file(&ldd_bus_type, &bus_attr_version))
167 printk(KERN_NOTICE "Unable to create version attribute\n");
168 ret = device_register(&ldd_bus);
169 if (ret)
170 printk(KERN_NOTICE "Unable to register ldd0\n");
171 return ret;
172 }
173
174 static void ldd_bus_exit(void)
175 {
176 device_unregister(&ldd_bus);
177 bus_unregister(&ldd_bus_type);
178 }
179
180 module_init(ldd_bus_init);
181 module_exit(ldd_bus_exit);
182
|
This page was automatically generated by the
LXR engine.
|