Skip to content

Commit ab121f3

Browse files
Linux Device Drivers 3 examples
0 parents  commit ab121f3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+13768
-0
lines changed

LICENSE

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
3+
Unless otherwise stated, the source code distributed with this book
4+
can be redistributed in source or binary form so long as an
5+
acknowledgment appears in derived source files. The citation should
6+
list that the code comes from BOOK by AUTHOR, published by O'Reilly &
7+
Associates. This code is under copyright and cannot be included in
8+
any other book, publication, or educational product without permission
9+
from O'Reilly & Associates. No warranty is attached; we cannot take
10+
responsibility for errors or fitness for use.
11+
12+
13+
There are a few exception to this licence, however: a few sources
14+
herein are distributed according to the GNU General Public License,
15+
version 2. You'll find a copy of the license in
16+
/usr/src/linux/COPYING, and in other places in your filesystem. The
17+
affected source files are:
18+
19+
pci/pci_skel.c
20+
tty/tiny_serial.c
21+
tty/tiny_tty.c
22+
usb/usb-skeleton.c
23+
24+
The files in ./pci ./tty and ./usb inherit the GPL from the kernel
25+
sources, as most of their code comes straight from the kernel
26+
(usb-skeleton.c being part of the kernel source tree directly.)
27+

Makefile

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
SUBDIRS = misc-progs misc-modules \
3+
skull scull scullc sculld scullp scullv sbull snull\
4+
short shortprint pci simple usb tty lddbus
5+
6+
all: subdirs
7+
8+
subdirs:
9+
for n in $(SUBDIRS); do $(MAKE) -C $$n || exit 1; done
10+
11+
clean:
12+
for n in $(SUBDIRS); do $(MAKE) -C $$n clean; done

include/lddbus.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Definitions for the virtual LDD bus.
3+
*
4+
* $Id: lddbus.h,v 1.4 2004/08/20 18:49:44 corbet Exp $
5+
*/
6+
7+
//extern struct device ldd_bus;
8+
extern struct bus_type ldd_bus_type;
9+
10+
11+
/*
12+
* The LDD driver type.
13+
*/
14+
15+
struct ldd_driver {
16+
char *version;
17+
struct module *module;
18+
struct device_driver driver;
19+
struct driver_attribute version_attr;
20+
};
21+
22+
#define to_ldd_driver(drv) container_of(drv, struct ldd_driver, driver);
23+
24+
/*
25+
* A device type for things "plugged" into the LDD bus.
26+
*/
27+
28+
struct ldd_device {
29+
char *name;
30+
struct ldd_driver *driver;
31+
struct device dev;
32+
};
33+
34+
#define to_ldd_device(dev) container_of(dev, struct ldd_device, dev);
35+
36+
extern int register_ldd_device(struct ldd_device *);
37+
extern void unregister_ldd_device(struct ldd_device *);
38+
extern int register_ldd_driver(struct ldd_driver *);
39+
extern void unregister_ldd_driver(struct ldd_driver *);

lddbus/Makefile

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Comment/uncomment the following line to disable/enable debugging
2+
#DEBUG = y
3+
4+
# Add your debugging flag (or not) to CFLAGS
5+
ifeq ($(DEBUG),y)
6+
DEBFLAGS = -O -g # "-O" is needed to expand inlines
7+
else
8+
DEBFLAGS = -O2
9+
endif
10+
CFLAGS += $(DEBFLAGS) -I$(LDDINCDIR)
11+
12+
13+
ifneq ($(KERNELRELEASE),)
14+
# call from kernel build system
15+
16+
obj-m := lddbus.o
17+
18+
else
19+
20+
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
21+
PWD := $(shell pwd)
22+
23+
default:
24+
$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) LDDINCDIR=$(PWD)/../include modules
25+
26+
endif
27+
28+
29+
30+
clean:
31+
rm -rf *.o *.ko *~ core .depend *.mod.c .*.cmd .tmp_versions .*.o.d
32+
33+
depend .depend dep:
34+
$(CC) $(CFLAGS) -M *.c > .depend
35+
36+
37+
ifeq (.depend,$(wildcard .depend))
38+
include .depend
39+
endif

lddbus/lddbus.c

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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+
static int ldd_hotplug(struct device *dev, char **envp, int num_envp,
34+
char *buffer, int buffer_size)
35+
{
36+
envp[0] = buffer;
37+
if (snprintf(buffer, buffer_size, "LDDBUS_VERSION=%s",
38+
Version) >= buffer_size)
39+
return -ENOMEM;
40+
envp[1] = NULL;
41+
return 0;
42+
}
43+
44+
/*
45+
* Match LDD devices to drivers. Just do a simple name test.
46+
*/
47+
static int ldd_match(struct device *dev, struct device_driver *driver)
48+
{
49+
return !strncmp(dev->bus_id, driver->name, strlen(driver->name));
50+
}
51+
52+
53+
/*
54+
* The LDD bus device.
55+
*/
56+
static void ldd_bus_release(struct device *dev)
57+
{
58+
printk(KERN_DEBUG "lddbus release\n");
59+
}
60+
61+
struct device ldd_bus = {
62+
.bus_id = "ldd0",
63+
.release = ldd_bus_release
64+
};
65+
66+
67+
/*
68+
* And the bus type.
69+
*/
70+
struct bus_type ldd_bus_type = {
71+
.name = "ldd",
72+
.match = ldd_match,
73+
.hotplug = ldd_hotplug,
74+
};
75+
76+
/*
77+
* Export a simple attribute.
78+
*/
79+
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
80+
{
81+
return snprintf(buf, PAGE_SIZE, "%s\n", Version);
82+
}
83+
84+
static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
85+
86+
87+
88+
/*
89+
* LDD devices.
90+
*/
91+
92+
/*
93+
* For now, no references to LDDbus devices go out which are not
94+
* tracked via the module reference count, so we use a no-op
95+
* release function.
96+
*/
97+
static void ldd_dev_release(struct device *dev)
98+
{ }
99+
100+
int register_ldd_device(struct ldd_device *ldddev)
101+
{
102+
ldddev->dev.bus = &ldd_bus_type;
103+
ldddev->dev.parent = &ldd_bus;
104+
ldddev->dev.release = ldd_dev_release;
105+
strncpy(ldddev->dev.bus_id, ldddev->name, BUS_ID_SIZE);
106+
return device_register(&ldddev->dev);
107+
}
108+
EXPORT_SYMBOL(register_ldd_device);
109+
110+
void unregister_ldd_device(struct ldd_device *ldddev)
111+
{
112+
device_unregister(&ldddev->dev);
113+
}
114+
EXPORT_SYMBOL(unregister_ldd_device);
115+
116+
/*
117+
* Crude driver interface.
118+
*/
119+
120+
121+
static ssize_t show_version(struct device_driver *driver, char *buf)
122+
{
123+
struct ldd_driver *ldriver = to_ldd_driver(driver);
124+
125+
sprintf(buf, "%s\n", ldriver->version);
126+
return strlen(buf);
127+
}
128+
129+
130+
int register_ldd_driver(struct ldd_driver *driver)
131+
{
132+
int ret;
133+
134+
driver->driver.bus = &ldd_bus_type;
135+
ret = driver_register(&driver->driver);
136+
if (ret)
137+
return ret;
138+
driver->version_attr.attr.name = "version";
139+
driver->version_attr.attr.owner = driver->module;
140+
driver->version_attr.attr.mode = S_IRUGO;
141+
driver->version_attr.show = show_version;
142+
driver->version_attr.store = NULL;
143+
return driver_create_file(&driver->driver, &driver->version_attr);
144+
}
145+
146+
void unregister_ldd_driver(struct ldd_driver *driver)
147+
{
148+
driver_unregister(&driver->driver);
149+
}
150+
EXPORT_SYMBOL(register_ldd_driver);
151+
EXPORT_SYMBOL(unregister_ldd_driver);
152+
153+
154+
155+
static int __init ldd_bus_init(void)
156+
{
157+
int ret;
158+
159+
ret = bus_register(&ldd_bus_type);
160+
if (ret)
161+
return ret;
162+
if (bus_create_file(&ldd_bus_type, &bus_attr_version))
163+
printk(KERN_NOTICE "Unable to create version attribute\n");
164+
ret = device_register(&ldd_bus);
165+
if (ret)
166+
printk(KERN_NOTICE "Unable to register ldd0\n");
167+
return ret;
168+
}
169+
170+
static void ldd_bus_exit(void)
171+
{
172+
device_unregister(&ldd_bus);
173+
bus_unregister(&ldd_bus_type);
174+
}
175+
176+
module_init(ldd_bus_init);
177+
module_exit(ldd_bus_exit);

misc-modules/Makefile

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
# To build modules outside of the kernel tree, we run "make"
3+
# in the kernel source tree; the Makefile these then includes this
4+
# Makefile once again.
5+
# This conditional selects whether we are being included from the
6+
# kernel Makefile or not.
7+
ifeq ($(KERNELRELEASE),)
8+
9+
# Assume the source tree is where the running kernel was built
10+
# You should set KERNELDIR in the environment if it's elsewhere
11+
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
12+
# The current directory is passed to sub-makes as argument
13+
PWD := $(shell pwd)
14+
15+
modules:
16+
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
17+
18+
modules_install:
19+
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
20+
21+
clean:
22+
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
23+
24+
.PHONY: modules modules_install clean
25+
26+
else
27+
# called from kernel build system: just declare what our modules are
28+
obj-m := hello.o hellop.o seq.o jit.o jiq.o sleepy.o complete.o \
29+
silly.o faulty.o kdatasize.o kdataalign.o
30+
endif
31+
32+

0 commit comments

Comments
 (0)