-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecho.c
110 lines (90 loc) · 2.21 KB
/
echo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/uio.h>
#include <sys/malloc.h>
#define BUFFER_SIZE 256
/* Forward declarations. */
static d_open_t echo_open;
static d_close_t echo_close;
static d_read_t echo_read;
static d_write_t echo_write;
static struct cdevsw echo_cdevsw = {
.d_version = D_VERSION,
.d_open = echo_open,
.d_close = echo_close,
.d_read = echo_read,
.d_write = echo_write,
.d_name = "echo"
};
typedef struct echo {
char buffer[BUFFER_SIZE];
int length;
} echo_t;
static echo_t *echo_message;
static struct cdev *echo_dev;
static int
echo_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
uprintf("Opening echo device.\n");
return(0);
}
static int
echo_close(struct cdev *dev, int fflags, int devtype, struct thread *td)
{
uprintf("Closing echo device.\n");
return(0);
}
static int
echo_write(struct cdev *dev, struct uio *uio, int ioflag)
{
int error = 0;
error = copyin(uio->uio_iov->iov_base, echo_message->buffer,
MIN(uio->uio_iov->iov_len, BUFFER_SIZE - 1));
if (error != 0) {
uprintf("Write failed.\n");
return (error);
}
*(echo_message->buffer +
MIN(uio->uio_iov->iov_len, BUFFER_SIZE - 1)) = 0;
echo_message->length = MIN(uio->uio_iov->iov_len, BUFFER_SIZE - 1);
return(error);
}
static int
echo_read(struct cdev *dev, struct uio *uio, int ioflag)
{
int error = 0;
int amount;
amount = MIN(uio->uio_resid,
(echo_message->length - uio->uio_offset > 0) ?
echo_message->length - uio->uio_offset : 0);
error = uiomove(echo_message->buffer + uio->uio_offset, amount, uio);
if (error != 0)
uprintf("Read failed.\n");
return (error);
}
static int
echo_modevent(module_t mod __unused, int event, void *arg __unused)
{
int error = 0;
switch (event) {
case MOD_LOAD:
echo_message = malloc(sizeof(echo_t), M_TEMP, M_WAITOK);
echo_dev = make_dev(&echo_cdevsw, 0, UID_ROOT, GID_WHEEL,
0600, "echo");
uprintf("Echo driver loaded.\n");
break;
case MOD_UNLOAD:
destroy_dev(echo_dev);
free(echo_message, M_TEMP);
uprintf("Echo driver unloaded.\n");
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}
DEV_MODULE(echo, echo_modevent, NULL);