Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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.