1 1.47 thorpej /* $NetBSD: wsevent.c,v 1.47 2021/09/26 01:16:10 thorpej Exp $ */ 2 1.18 jmmv 3 1.18 jmmv /*- 4 1.26 ad * Copyright (c) 2006, 2008 The NetBSD Foundation, Inc. 5 1.18 jmmv * All rights reserved. 6 1.18 jmmv * 7 1.18 jmmv * This code is derived from software contributed to The NetBSD Foundation 8 1.18 jmmv * by Julio M. Merino Vidal. 9 1.18 jmmv * 10 1.18 jmmv * Redistribution and use in source and binary forms, with or without 11 1.18 jmmv * modification, are permitted provided that the following conditions 12 1.18 jmmv * are met: 13 1.18 jmmv * 1. Redistributions of source code must retain the above copyright 14 1.18 jmmv * notice, this list of conditions and the following disclaimer. 15 1.18 jmmv * 2. Redistributions in binary form must reproduce the above copyright 16 1.18 jmmv * notice, this list of conditions and the following disclaimer in the 17 1.18 jmmv * documentation and/or other materials provided with the distribution. 18 1.18 jmmv * 19 1.18 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.18 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.18 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.18 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.18 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.18 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.18 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.18 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.18 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.18 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.18 jmmv * POSSIBILITY OF SUCH DAMAGE. 30 1.18 jmmv */ 31 1.1 drochner 32 1.1 drochner /* 33 1.1 drochner * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 34 1.1 drochner * 35 1.1 drochner * Redistribution and use in source and binary forms, with or without 36 1.1 drochner * modification, are permitted provided that the following conditions 37 1.1 drochner * are met: 38 1.1 drochner * 1. Redistributions of source code must retain the above copyright 39 1.1 drochner * notice, this list of conditions and the following disclaimer. 40 1.1 drochner * 2. Redistributions in binary form must reproduce the above copyright 41 1.1 drochner * notice, this list of conditions and the following disclaimer in the 42 1.1 drochner * documentation and/or other materials provided with the distribution. 43 1.1 drochner * 3. All advertising materials mentioning features or use of this software 44 1.1 drochner * must display the following acknowledgement: 45 1.1 drochner * This product includes software developed by Christopher G. Demetriou 46 1.1 drochner * for the NetBSD Project. 47 1.1 drochner * 4. The name of the author may not be used to endorse or promote products 48 1.1 drochner * derived from this software without specific prior written permission 49 1.1 drochner * 50 1.1 drochner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 51 1.1 drochner * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 52 1.1 drochner * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 53 1.1 drochner * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 54 1.1 drochner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 55 1.1 drochner * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 1.1 drochner * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 1.1 drochner * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 1.1 drochner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 59 1.1 drochner * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 1.1 drochner */ 61 1.1 drochner 62 1.1 drochner /* 63 1.1 drochner * Copyright (c) 1992, 1993 64 1.1 drochner * The Regents of the University of California. All rights reserved. 65 1.1 drochner * 66 1.1 drochner * This software was developed by the Computer Systems Engineering group 67 1.1 drochner * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 68 1.1 drochner * contributed to Berkeley. 69 1.1 drochner * 70 1.1 drochner * All advertising materials mentioning features or use of this software 71 1.1 drochner * must display the following acknowledgement: 72 1.1 drochner * This product includes software developed by the University of 73 1.1 drochner * California, Lawrence Berkeley Laboratory. 74 1.1 drochner * 75 1.1 drochner * Redistribution and use in source and binary forms, with or without 76 1.1 drochner * modification, are permitted provided that the following conditions 77 1.1 drochner * are met: 78 1.1 drochner * 1. Redistributions of source code must retain the above copyright 79 1.1 drochner * notice, this list of conditions and the following disclaimer. 80 1.1 drochner * 2. Redistributions in binary form must reproduce the above copyright 81 1.1 drochner * notice, this list of conditions and the following disclaimer in the 82 1.1 drochner * documentation and/or other materials provided with the distribution. 83 1.16 agc * 3. Neither the name of the University nor the names of its contributors 84 1.1 drochner * may be used to endorse or promote products derived from this software 85 1.1 drochner * without specific prior written permission. 86 1.1 drochner * 87 1.1 drochner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 88 1.1 drochner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 89 1.1 drochner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 90 1.1 drochner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 91 1.1 drochner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 92 1.1 drochner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 93 1.1 drochner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 94 1.1 drochner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 95 1.1 drochner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 96 1.1 drochner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 97 1.1 drochner * SUCH DAMAGE. 98 1.1 drochner * 99 1.1 drochner * @(#)event.c 8.1 (Berkeley) 6/11/93 100 1.1 drochner */ 101 1.1 drochner 102 1.1 drochner /* 103 1.1 drochner * Internal "wscons_event" queue interface for the keyboard and mouse drivers. 104 1.1 drochner */ 105 1.9 lukem 106 1.9 lukem #include <sys/cdefs.h> 107 1.47 thorpej __KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.47 2021/09/26 01:16:10 thorpej Exp $"); 108 1.28 christos 109 1.36 pooka #ifdef _KERNEL_OPT 110 1.28 christos #include "opt_compat_netbsd.h" 111 1.33 apb #include "opt_modular.h" 112 1.36 pooka #endif 113 1.1 drochner 114 1.1 drochner #include <sys/param.h> 115 1.18 jmmv #include <sys/kernel.h> 116 1.1 drochner #include <sys/fcntl.h> 117 1.32 yamt #include <sys/kmem.h> 118 1.1 drochner #include <sys/proc.h> 119 1.1 drochner #include <sys/systm.h> 120 1.1 drochner #include <sys/vnode.h> 121 1.1 drochner #include <sys/select.h> 122 1.1 drochner #include <sys/poll.h> 123 1.40 pgoyette #include <sys/compat_stub.h> 124 1.43 mlelstv #include <sys/sysctl.h> 125 1.1 drochner 126 1.1 drochner #include <dev/wscons/wsconsio.h> 127 1.1 drochner #include <dev/wscons/wseventvar.h> 128 1.1 drochner 129 1.1 drochner /* 130 1.18 jmmv * Size of a wsevent queue (measured in number of events). 131 1.18 jmmv * Should be a power of two so that `%' is fast. 132 1.18 jmmv * At the moment, the value below makes the queues use 2 Kbytes each; this 133 1.18 jmmv * value may need tuning. 134 1.18 jmmv */ 135 1.18 jmmv #define WSEVENT_QSIZE 256 136 1.18 jmmv 137 1.32 yamt #define EVSIZE(ver) ((ver) == WSEVENT_VERSION ? \ 138 1.32 yamt sizeof(struct wscons_event) : \ 139 1.32 yamt sizeof(struct owscons_event)) 140 1.32 yamt #define EVARRAY(ev, idx) (&(ev)->q[(idx)]) 141 1.32 yamt 142 1.43 mlelstv static int wsevent_default_version = WSEVENT_VERSION; 143 1.43 mlelstv 144 1.18 jmmv /* 145 1.18 jmmv * Priority of code managing wsevent queues. PWSEVENT is set just above 146 1.18 jmmv * PSOCK, which is just above TTIPRI, on the theory that mouse and keyboard 147 1.18 jmmv * `user' input should be quick. 148 1.18 jmmv */ 149 1.18 jmmv #define PWSEVENT 23 150 1.18 jmmv #define splwsevent() spltty() 151 1.18 jmmv 152 1.26 ad static void wsevent_intr(void *); 153 1.26 ad 154 1.18 jmmv /* 155 1.1 drochner * Initialize a wscons_event queue. 156 1.1 drochner */ 157 1.1 drochner void 158 1.18 jmmv wsevent_init(struct wseventvar *ev, struct proc *p) 159 1.1 drochner { 160 1.1 drochner 161 1.13 christos if (ev->q != NULL) { 162 1.7 augustss #ifdef DIAGNOSTIC 163 1.7 augustss printf("wsevent_init: already init\n"); 164 1.13 christos #endif 165 1.7 augustss return; 166 1.7 augustss } 167 1.44 pgoyette /* 168 1.44 pgoyette * For binary compat set default version and either build with 169 1.43 mlelstv * COMPAT_50 or load COMPAT_50 module to include the compatibility 170 1.43 mlelstv * code. 171 1.43 mlelstv */ 172 1.43 mlelstv if (wsevent_default_version >= 0 && 173 1.43 mlelstv wsevent_default_version < WSEVENT_VERSION) 174 1.43 mlelstv ev->version = wsevent_default_version; 175 1.43 mlelstv else 176 1.43 mlelstv ev->version = WSEVENT_VERSION; 177 1.43 mlelstv 178 1.1 drochner ev->get = ev->put = 0; 179 1.32 yamt ev->q = kmem_alloc(WSEVENT_QSIZE * sizeof(*ev->q), KM_SLEEP); 180 1.25 rmind selinit(&ev->sel); 181 1.18 jmmv ev->io = p; 182 1.26 ad ev->sih = softint_establish(SOFTINT_MPSAFE | SOFTINT_CLOCK, 183 1.26 ad wsevent_intr, ev); 184 1.1 drochner } 185 1.1 drochner 186 1.1 drochner /* 187 1.1 drochner * Tear down a wscons_event queue. 188 1.1 drochner */ 189 1.1 drochner void 190 1.6 augustss wsevent_fini(struct wseventvar *ev) 191 1.1 drochner { 192 1.13 christos if (ev->q == NULL) { 193 1.13 christos #ifdef DIAGNOSTIC 194 1.13 christos printf("wsevent_fini: already fini\n"); 195 1.13 christos #endif 196 1.13 christos return; 197 1.13 christos } 198 1.25 rmind seldestroy(&ev->sel); 199 1.32 yamt kmem_free(ev->q, WSEVENT_QSIZE * sizeof(*ev->q)); 200 1.7 augustss ev->q = NULL; 201 1.26 ad softint_disestablish(ev->sih); 202 1.1 drochner } 203 1.1 drochner 204 1.32 yamt static int 205 1.32 yamt wsevent_copyout_events(const struct wscons_event *events, int cnt, 206 1.32 yamt struct uio *uio, int ver) 207 1.32 yamt { 208 1.40 pgoyette int error; 209 1.32 yamt 210 1.32 yamt switch (ver) { 211 1.32 yamt case 0: 212 1.42 pgoyette MODULE_HOOK_CALL(wscons_copyout_events_50_hook, 213 1.40 pgoyette (events, cnt, uio), enosys(), error); 214 1.40 pgoyette if (error == ENOSYS) 215 1.40 pgoyette error = EINVAL; 216 1.40 pgoyette return error; 217 1.32 yamt case WSEVENT_VERSION: 218 1.32 yamt return uiomove(__UNCONST(events), cnt * sizeof(*events), uio); 219 1.32 yamt default: 220 1.32 yamt panic("%s: unknown version %d", __func__, ver); 221 1.32 yamt } 222 1.32 yamt } 223 1.32 yamt 224 1.1 drochner /* 225 1.1 drochner * User-level interface: read, poll. 226 1.1 drochner * (User cannot write an event queue.) 227 1.1 drochner */ 228 1.1 drochner int 229 1.6 augustss wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) 230 1.1 drochner { 231 1.1 drochner int s, n, cnt, error; 232 1.32 yamt const int ver = ev->version; 233 1.32 yamt const size_t evsize = EVSIZE(ver); 234 1.1 drochner 235 1.1 drochner /* 236 1.1 drochner * Make sure we can return at least 1. 237 1.1 drochner */ 238 1.32 yamt if (uio->uio_resid < evsize) 239 1.1 drochner return (EMSGSIZE); /* ??? */ 240 1.1 drochner s = splwsevent(); 241 1.1 drochner while (ev->get == ev->put) { 242 1.1 drochner if (flags & IO_NDELAY) { 243 1.1 drochner splx(s); 244 1.1 drochner return (EWOULDBLOCK); 245 1.1 drochner } 246 1.1 drochner ev->wanted = 1; 247 1.28 christos error = tsleep(ev, PWSEVENT | PCATCH, "wsevent_read", 0); 248 1.1 drochner if (error) { 249 1.1 drochner splx(s); 250 1.1 drochner return (error); 251 1.1 drochner } 252 1.1 drochner } 253 1.1 drochner /* 254 1.1 drochner * Move wscons_event from tail end of queue (there is at least one 255 1.1 drochner * there). 256 1.1 drochner */ 257 1.1 drochner if (ev->put < ev->get) 258 1.1 drochner cnt = WSEVENT_QSIZE - ev->get; /* events in [get..QSIZE) */ 259 1.1 drochner else 260 1.1 drochner cnt = ev->put - ev->get; /* events in [get..put) */ 261 1.1 drochner splx(s); 262 1.32 yamt n = howmany(uio->uio_resid, evsize); 263 1.1 drochner if (cnt > n) 264 1.1 drochner cnt = n; 265 1.32 yamt error = wsevent_copyout_events(EVARRAY(ev, ev->get), cnt, uio, ver); 266 1.1 drochner n -= cnt; 267 1.1 drochner /* 268 1.1 drochner * If we do not wrap to 0, used up all our space, or had an error, 269 1.1 drochner * stop. Otherwise move from front of queue to put index, if there 270 1.1 drochner * is anything there to move. 271 1.1 drochner */ 272 1.1 drochner if ((ev->get = (ev->get + cnt) % WSEVENT_QSIZE) != 0 || 273 1.1 drochner n == 0 || error || (cnt = ev->put) == 0) 274 1.1 drochner return (error); 275 1.1 drochner if (cnt > n) 276 1.1 drochner cnt = n; 277 1.32 yamt error = wsevent_copyout_events(EVARRAY(ev, 0), cnt, uio, ver); 278 1.1 drochner ev->get = cnt; 279 1.1 drochner return (error); 280 1.1 drochner } 281 1.1 drochner 282 1.1 drochner int 283 1.17 christos wsevent_poll(struct wseventvar *ev, int events, struct lwp *l) 284 1.1 drochner { 285 1.1 drochner int revents = 0; 286 1.1 drochner int s = splwsevent(); 287 1.1 drochner 288 1.2 thorpej if (events & (POLLIN | POLLRDNORM)) { 289 1.1 drochner if (ev->get != ev->put) 290 1.2 thorpej revents |= events & (POLLIN | POLLRDNORM); 291 1.2 thorpej else 292 1.17 christos selrecord(l, &ev->sel); 293 1.2 thorpej } 294 1.1 drochner 295 1.1 drochner splx(s); 296 1.1 drochner return (revents); 297 1.11 jdolecek } 298 1.11 jdolecek 299 1.11 jdolecek static void 300 1.11 jdolecek filt_wseventrdetach(struct knote *kn) 301 1.11 jdolecek { 302 1.11 jdolecek struct wseventvar *ev = kn->kn_hook; 303 1.11 jdolecek int s; 304 1.11 jdolecek 305 1.11 jdolecek s = splwsevent(); 306 1.46 thorpej selremove_knote(&ev->sel, kn); 307 1.11 jdolecek splx(s); 308 1.11 jdolecek } 309 1.11 jdolecek 310 1.11 jdolecek static int 311 1.22 christos filt_wseventread(struct knote *kn, long hint) 312 1.11 jdolecek { 313 1.11 jdolecek struct wseventvar *ev = kn->kn_hook; 314 1.11 jdolecek 315 1.11 jdolecek if (ev->get == ev->put) 316 1.11 jdolecek return (0); 317 1.11 jdolecek 318 1.11 jdolecek if (ev->get < ev->put) 319 1.11 jdolecek kn->kn_data = ev->put - ev->get; 320 1.11 jdolecek else 321 1.28 christos kn->kn_data = (WSEVENT_QSIZE - ev->get) + ev->put; 322 1.11 jdolecek 323 1.32 yamt kn->kn_data *= EVSIZE(ev->version); 324 1.11 jdolecek 325 1.11 jdolecek return (1); 326 1.11 jdolecek } 327 1.11 jdolecek 328 1.37 maya static const struct filterops wsevent_filtops = { 329 1.47 thorpej .f_flags = FILTEROP_ISFD, 330 1.37 maya .f_attach = NULL, 331 1.37 maya .f_detach = filt_wseventrdetach, 332 1.37 maya .f_event = filt_wseventread, 333 1.37 maya }; 334 1.11 jdolecek 335 1.11 jdolecek int 336 1.11 jdolecek wsevent_kqfilter(struct wseventvar *ev, struct knote *kn) 337 1.11 jdolecek { 338 1.11 jdolecek int s; 339 1.11 jdolecek 340 1.11 jdolecek switch (kn->kn_filter) { 341 1.11 jdolecek case EVFILT_READ: 342 1.11 jdolecek kn->kn_fop = &wsevent_filtops; 343 1.11 jdolecek break; 344 1.11 jdolecek 345 1.11 jdolecek default: 346 1.24 pooka return (EINVAL); 347 1.11 jdolecek } 348 1.11 jdolecek 349 1.11 jdolecek kn->kn_hook = ev; 350 1.11 jdolecek 351 1.11 jdolecek s = splwsevent(); 352 1.46 thorpej selrecord_knote(&ev->sel, kn); 353 1.11 jdolecek splx(s); 354 1.11 jdolecek 355 1.11 jdolecek return (0); 356 1.1 drochner } 357 1.18 jmmv 358 1.18 jmmv /* 359 1.18 jmmv * Wakes up all listener of the 'ev' queue. 360 1.18 jmmv */ 361 1.18 jmmv void 362 1.18 jmmv wsevent_wakeup(struct wseventvar *ev) 363 1.18 jmmv { 364 1.18 jmmv 365 1.25 rmind selnotify(&ev->sel, 0, 0); 366 1.18 jmmv 367 1.18 jmmv if (ev->wanted) { 368 1.18 jmmv ev->wanted = 0; 369 1.18 jmmv wakeup(ev); 370 1.18 jmmv } 371 1.18 jmmv 372 1.23 ad if (ev->async) { 373 1.26 ad softint_schedule(ev->sih); 374 1.26 ad } 375 1.26 ad } 376 1.26 ad 377 1.26 ad /* 378 1.26 ad * Soft interrupt handler: sends signal to async proc. 379 1.26 ad */ 380 1.26 ad static void 381 1.26 ad wsevent_intr(void *cookie) 382 1.26 ad { 383 1.26 ad struct wseventvar *ev; 384 1.26 ad 385 1.26 ad ev = cookie; 386 1.26 ad 387 1.26 ad if (ev->async) { 388 1.45 ad mutex_enter(&proc_lock); 389 1.18 jmmv psignal(ev->io, SIGIO); 390 1.45 ad mutex_exit(&proc_lock); 391 1.23 ad } 392 1.18 jmmv } 393 1.18 jmmv 394 1.18 jmmv /* 395 1.20 uebayasi * Injects the set of events given in 'events', whose size is 'nevents', 396 1.18 jmmv * into the 'ev' queue. If there is not enough free space to inject them 397 1.18 jmmv * all, returns ENOSPC and the queue is left intact; otherwise returns 0 398 1.18 jmmv * and wakes up all listeners. 399 1.18 jmmv */ 400 1.18 jmmv int 401 1.18 jmmv wsevent_inject(struct wseventvar *ev, struct wscons_event *events, 402 1.18 jmmv size_t nevents) 403 1.18 jmmv { 404 1.18 jmmv size_t avail, i; 405 1.18 jmmv struct timespec t; 406 1.18 jmmv 407 1.18 jmmv /* Calculate number of free slots in the queue. */ 408 1.18 jmmv if (ev->put < ev->get) 409 1.18 jmmv avail = ev->get - ev->put; 410 1.18 jmmv else 411 1.18 jmmv avail = WSEVENT_QSIZE - (ev->put - ev->get); 412 1.18 jmmv KASSERT(avail <= WSEVENT_QSIZE); 413 1.18 jmmv 414 1.18 jmmv /* Fail if there is all events will not fit in the queue. */ 415 1.18 jmmv if (avail < nevents) 416 1.18 jmmv return ENOSPC; 417 1.18 jmmv 418 1.18 jmmv /* Use the current time for all events. */ 419 1.19 kardel getnanotime(&t); 420 1.18 jmmv 421 1.18 jmmv /* Inject the events. */ 422 1.32 yamt for (i = 0; i < nevents; i++) { 423 1.32 yamt struct wscons_event *we; 424 1.28 christos 425 1.32 yamt we = EVARRAY(ev, ev->put); 426 1.32 yamt we->type = events[i].type; 427 1.32 yamt we->value = events[i].value; 428 1.32 yamt we->time = t; 429 1.28 christos 430 1.32 yamt ev->put = (ev->put + 1) % WSEVENT_QSIZE; 431 1.18 jmmv } 432 1.18 jmmv wsevent_wakeup(ev); 433 1.18 jmmv 434 1.18 jmmv return 0; 435 1.18 jmmv } 436 1.28 christos 437 1.28 christos int 438 1.28 christos wsevent_setversion(struct wseventvar *ev, int vers) 439 1.28 christos { 440 1.28 christos if (ev == NULL) 441 1.28 christos return EINVAL; 442 1.28 christos 443 1.28 christos switch (vers) { 444 1.28 christos case 0: 445 1.28 christos case WSEVENT_VERSION: 446 1.28 christos break; 447 1.28 christos default: 448 1.28 christos return EINVAL; 449 1.28 christos } 450 1.28 christos 451 1.28 christos if (vers == ev->version) 452 1.28 christos return 0; 453 1.28 christos 454 1.28 christos ev->get = ev->put = 0; 455 1.28 christos ev->version = vers; 456 1.28 christos return 0; 457 1.28 christos } 458 1.43 mlelstv 459 1.43 mlelstv SYSCTL_SETUP(sysctl_wsevent_setup, "sysctl hw.wsevent subtree setup") 460 1.43 mlelstv { 461 1.43 mlelstv const struct sysctlnode *node = NULL; 462 1.43 mlelstv 463 1.43 mlelstv if (sysctl_createv(clog, 0, NULL, &node, 464 1.43 mlelstv CTLFLAG_PERMANENT, 465 1.43 mlelstv CTLTYPE_NODE, "wsevent", NULL, 466 1.43 mlelstv NULL, 0, NULL, 0, 467 1.43 mlelstv CTL_HW, CTL_CREATE, CTL_EOL) != 0) 468 1.43 mlelstv return; 469 1.43 mlelstv 470 1.43 mlelstv sysctl_createv(clog, 0, &node, NULL, 471 1.43 mlelstv CTLFLAG_READWRITE, 472 1.43 mlelstv CTLTYPE_INT, "default_version", 473 1.43 mlelstv SYSCTL_DESCR("Set default event version for compatibility"), 474 1.43 mlelstv NULL, 0, &wsevent_default_version, 0, 475 1.43 mlelstv CTL_CREATE, CTL_EOL); 476 1.43 mlelstv } 477