2 #include <sys/systm.h> /* for uiomove(9) */
4 /*#include <sys/errno.h>*/
6 #include <sys/device.h>
8 #include <sys/malloc.h> /* for free(9) */
10 #include <sys/kauth.h>
11 #include <sys/syslog.h>
12 #include <prop/proplib.h>
14 /* These macros expand to function prototypes needed for autoconf(9) */
15 void mydevattach(struct device
*parent
, struct device
*self
, void *aux
);
16 static dev_type_open(mydevopen
);
17 static dev_type_close(mydevclose
);
18 static dev_type_read(mydevread
);
19 static dev_type_ioctl(mydevioctl
);
21 static struct mydev_softc
{
22 struct device sc_mydev
; /* generic device info */
24 unsigned int sc_usage
; /* number of open devices */
28 * Each device driver must present to the system a standard
29 * autoconfiguration interface. See driver(9).
31 CFATTACH_DECL(mydev
, /* driver name */
32 sizeof (struct mydev_softc
), /* size of instance data */
33 NULL
, /* match/probe function */
34 mydevattach
, /* attach function */
35 NULL
, /* detach function */
36 NULL
); /* activate function */
38 /* Define the character dev handlers */
39 const struct cdevsw mydev_cdevsw
= {
54 * This private buffer is the pool we draw data from
55 * and send them over to userspace upon a read() request.
57 static char mybuffer
[] = "This is a test";
60 * Attach for autoconfig to find.
63 mydevattach(struct device
*parent
, struct device
*self
, void *aux
)
66 * This is where resources that need to be allocated/initialised
67 * can be set up, prior to xxxopen() call.
69 log(LOG_DEBUG
, "mydev: pseudo-device attached\n");
70 mydev_softc
.sc_usage
= 0;
74 * Handle an open request on the dev.
77 mydevopen(dev_t dev
, int flags
, int fmt
, struct lwp
*proc
)
79 log(LOG_DEBUG
, "mydev: pseudo-device open attempt by "
80 "uid=%u, pid=%u. (dev=%u, major=%d, minor=%d)\n",
81 kauth_cred_geteuid(proc
->l_cred
), proc
->l_proc
->p_pid
,
82 dev
, major(dev
), minor(dev
));
84 if (mydev_softc
.sc_usage
> 0) {
85 log(LOG_ERR
, "mydev: pseudo-device already in use\n");
89 mydev_softc
.sc_usage
++;
91 return 0; /* Success */
95 * Handle the close request for the dev.
98 mydevclose(dev_t dev
, int flags
, int fmt
, struct lwp
*proc
)
100 if (mydev_softc
.sc_usage
> 0)
101 mydev_softc
.sc_usage
--;
103 log(LOG_DEBUG
, "mydev: pseudo-device closed\n");
105 return 0; /* Success */
109 * Handle read request on the dev.
112 mydevread(dev_t dev
, struct uio
*uio
, int ioflag
)
117 log(LOG_DEBUG
, "mydev: uio: iov = %p, iovcnt = %d, resid = %u, vmspace = %p\n",
118 uio
->uio_iov
, uio
->uio_iovcnt
, uio
->uio_resid
, uio
->uio_vmspace
);
120 while (uio
->uio_resid
> 0) {
121 nbytes
= MIN(uio
->uio_resid
, sizeof mybuffer
);
122 if ((ret
= uiomove(mybuffer
, nbytes
, uio
)) != 0)
123 return ret
; /* Error */
126 return 0; /* Success */
131 * Handle the ioctl for the dev.
134 mydevioctl(dev_t dev
, u_long cmd
, caddr_t data
, int flags
,
137 const struct mydev_params
*params
;
138 const struct plistref
*pref
;
140 prop_dictionary_t dict
;
146 /* Pass data from userspace to kernel in the conventional way */
147 params
= (const struct mydev_params
*)data
;
148 log(LOG_DEBUG
, "mydev: got number of %d and string of %s\n",
149 params
->number
, params
->string
);
153 /* Use proplib(3) for userspace/kernel communication */
154 pref
= (const struct plistref
*)data
;
155 error
= prop_dictionary_copyin_ioctl(pref
, cmd
, &dict
);
159 /* Print dict's count for debugging purposes */
160 log(LOG_DEBUG
, "mydev: dict count = %u\n",
161 prop_dictionary_count(dict
));
163 /* Retrieve object associated with "key" key */
164 po
= prop_dictionary_get(dict
, "key");
165 if (po
== NULL
|| prop_object_type(po
) != PROP_TYPE_STRING
) {
166 log(LOG_DEBUG
, "mydev: prop_dictionary_get() failed\n");
167 prop_object_release(dict
);
172 val
= prop_string_cstring(po
);
174 log(LOG_DEBUG
, "mydev: prop_string_cstring() failed\n");
175 prop_object_release(po
);
176 prop_object_release(dict
);
179 prop_object_release(po
);
180 log(LOG_DEBUG
, "mydev: <x, y> = (%s, %s)\n", "key", val
);
184 prop_object_release(dict
);
188 /* Inappropriate ioctl for device */