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