Character device driver
Topics in this section,
In this section, you are going to learn
How to write a Character Device Driver module ?
# |
Version |
---|---|
Freebsd |
14.1.0 |
Create directory using mkdir command
test:~$ pwd
/home/test/
test:~$ mkdir char_device_drivers
test:~$ cd char_device_drivers
test:~$ pwd
home/test/char_device_drivers
Architecture
test:~$
test:~$
Source path : |
c1 |
Bin path : |
c2 |
List of C files |
c3 |
NM output : |
c4 |
Load file : |
c5 |
1#include <sys/types.h>
2#include <sys/systm.h> /* uprintf */
3#include <sys/param.h> /* defines used in kernel.h */
4#include <sys/module.h>
5#include <sys/kernel.h> /* types used in module initialization */
6#include <sys/conf.h> /* cdevsw struct */
7#include <sys/uio.h> /* uio struct */
8#include <sys/malloc.h>
9
10#define BUFFERSIZE 255
11
12/* Function prototypes */
13static d_open_t echo_open;
14static d_close_t echo_close;
15static d_read_t echo_read;
16static d_write_t echo_write;
17
18/* Character device entry points */
19static struct cdevsw echo_cdevsw = {
20 .d_version = D_VERSION,
21 .d_open = echo_open,
22 .d_close = echo_close,
23 .d_read = echo_read,
24 .d_write = echo_write,
25 .d_name = "echo",
26};
27
28struct s_echo {
29 char msg[BUFFERSIZE + 1];
30 int len;
31};
32
33/* vars */
34static struct cdev *echo_dev;
35static struct s_echo *echomsg;
36
37MALLOC_DECLARE(M_ECHOBUF);
38MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
39
40static int
41echo_loader(struct module *m __unused, int what, void *arg __unused)
42{
43 int error = 0;
44
45 switch (what) {
46 case MOD_LOAD: /* kldload */
47 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
48 &echo_dev,
49 &echo_cdevsw,
50 0,
51 UID_ROOT,
52 GID_WHEEL,
53 0600,
54 "echo");
55 if (error != 0)
56 break;
57
58 echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK |
59 M_ZERO);
60 printf("Echo device loaded.\n");
61 break;
62 case MOD_UNLOAD:
63 destroy_dev(echo_dev);
64 free(echomsg, M_ECHOBUF);
65 printf("Echo device unloaded.\n");
66 break;
67 default:
68 error = EOPNOTSUPP;
69 break;
70 }
71 return (error);
72}
73
74static int
75echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,
76 struct thread *td __unused)
77{
78 int error = 0;
79
80 uprintf("Opened device \"echo\" successfully.\n");
81 return (error);
82}
83
84static int
85echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,
86 struct thread *td __unused)
87{
88
89 uprintf("\nClosing device \"echo\".\n");
90 return (0);
91}
92
93static int
94echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
95{
96 size_t amt;
97 int error;
98
99 amt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? 0 :
100 echomsg->len + 1 - uio->uio_offset);
101
102 if ((error = uiomove(echomsg->msg, amt, uio)) != 0)
103 uprintf("uiomove failed!\n");
104
105 return (error);
106}
107
108static int
109echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
110{
111 size_t amt;
112 int error;
113
114 if (uio->uio_offset != 0 && (uio->uio_offset != echomsg->len))
115 return (EINVAL);
116
117 /* This is a new message, reset length */
118 if (uio->uio_offset == 0)
119 echomsg->len = 0;
120
121 /* Copy the string in from user memory to kernel memory */
122 amt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len));
123
124 error = uiomove(echomsg->msg + uio->uio_offset, amt, uio);
125
126 /* Now we need to null terminate and record the length */
127 echomsg->len = uio->uio_offset;
128 echomsg->msg[echomsg->len] = 0;
129
130 if (error != 0)
131 uprintf("Write failed: bad address!\n");
132 return (error);
133}
134
135DEV_MODULE(echo, echo_loader, NULL);
1SRCS=char.c
2KMOD=echo
3
4.include <bsd.kmod.mk>
1test:~$ pwd
2home/test/char_device_drivers
3
4
5test:~$ ls
6char.c Makefile README
7
8
9test:~$ make
1test:~$ kldload -v ./echo.ko
1test:~$ dmesg
2Echo device loaded.
Writing data to the driver (/dev/echo)
1test:~$ echo -n "Test Data" > /dev/echo
2Opened device "echo" successfully.
3
4Closing device "echo".
Reading data from the driver (/dev/echo)
1test:~$ cat /dev/echo
2Opened device "echo" successfully.
3Test Data
4Closing device "echo".
1test:~$ kldunload echo
1test:~$ dmesg
2Echo device unloaded.
Open nl80211.c file with vim, add prints in all .doit functions in nl80211_small_ops
test:~$
Open nl80211.c file with vim, add prints in all .doit functions in nl80211_small_ops
test:~$
test:~$
test:~$