Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/wscons/wsevent.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/wscons/wsevent.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.26 retrieving revision 1.26.2.2 diff -u -p -r1.26 -r1.26.2.2 --- src/sys/dev/wscons/wsevent.c 2008/04/24 15:35:28 1.26 +++ src/sys/dev/wscons/wsevent.c 2009/05/04 08:13:25 1.26.2.2 @@ -1,4 +1,4 @@ -/* $NetBSD: wsevent.c,v 1.26 2008/04/24 15:35:28 ad Exp $ */ +/* $NetBSD: wsevent.c,v 1.26.2.2 2009/05/04 08:13:25 yamt Exp $ */ /*- * Copyright (c) 2006, 2008 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -111,12 +104,15 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.26 2008/04/24 15:35:28 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.26.2.2 2009/05/04 08:13:25 yamt Exp $"); + +#include "opt_compat_netbsd.h" +#include "opt_modular.h" #include #include #include -#include +#include #include #include #include @@ -134,6 +130,11 @@ __KERNEL_RCSID(0, "$NetBSD: wsevent.c,v */ #define WSEVENT_QSIZE 256 +#define EVSIZE(ver) ((ver) == WSEVENT_VERSION ? \ + sizeof(struct wscons_event) : \ + sizeof(struct owscons_event)) +#define EVARRAY(ev, idx) (&(ev)->q[(idx)]) + /* * Priority of code managing wsevent queues. PWSEVENT is set just above * PSOCK, which is just above TTIPRI, on the theory that mouse and keyboard @@ -157,9 +158,9 @@ wsevent_init(struct wseventvar *ev, stru #endif return; } + ev->version = 0; ev->get = ev->put = 0; - ev->q = malloc((u_long)WSEVENT_QSIZE * sizeof(struct wscons_event), - M_DEVBUF, M_WAITOK|M_ZERO); + ev->q = kmem_alloc(WSEVENT_QSIZE * sizeof(*ev->q), KM_SLEEP); selinit(&ev->sel); ev->io = p; ev->sih = softint_establish(SOFTINT_MPSAFE | SOFTINT_CLOCK, @@ -179,11 +180,59 @@ wsevent_fini(struct wseventvar *ev) return; } seldestroy(&ev->sel); - free(ev->q, M_DEVBUF); + kmem_free(ev->q, WSEVENT_QSIZE * sizeof(*ev->q)); ev->q = NULL; softint_disestablish(ev->sih); } +#if defined(COMPAT_50) || defined(MODULAR) +static int +wsevent_copyout_events50(const struct wscons_event *events, int cnt, + struct uio *uio) +{ + int i; + + for (i = 0; i < cnt; i++) { + const struct wscons_event *ev = &events[i]; + struct owscons_event ev50; + int error; + + ev50.type = ev->type; + ev50.value = ev->value; + timespec_to_timespec50(&ev->time, &ev50.time); + + error = uiomove(&ev50, sizeof(ev50), uio); + if (error) { + return error; + } + } + return 0; +} +#else /* defined(COMPAT_50) || defined(MODULAR) */ +static int +wsevent_copyout_events50(const struct wscons_event *events, int cnt, + struct uio *uio) +{ + + return EINVAL; +} +#endif /* defined(COMPAT_50) || defined(MODULAR) */ + +static int +wsevent_copyout_events(const struct wscons_event *events, int cnt, + struct uio *uio, int ver) +{ + + switch (ver) { + case 0: + return wsevent_copyout_events50(events, cnt, uio); + case WSEVENT_VERSION: + return uiomove(__UNCONST(events), cnt * sizeof(*events), uio); + default: + panic("%s: unknown version %d", __func__, ver); + } +} + /* * User-level interface: read, poll. * (User cannot write an event queue.) @@ -192,11 +241,13 @@ int wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) { int s, n, cnt, error; + const int ver = ev->version; + const size_t evsize = EVSIZE(ver); /* * Make sure we can return at least 1. */ - if (uio->uio_resid < sizeof(struct wscons_event)) + if (uio->uio_resid < evsize) return (EMSGSIZE); /* ??? */ s = splwsevent(); while (ev->get == ev->put) { @@ -205,8 +256,7 @@ wsevent_read(struct wseventvar *ev, stru return (EWOULDBLOCK); } ev->wanted = 1; - error = tsleep(ev, PWSEVENT | PCATCH, - "wsevent_read", 0); + error = tsleep(ev, PWSEVENT | PCATCH, "wsevent_read", 0); if (error) { splx(s); return (error); @@ -221,11 +271,10 @@ wsevent_read(struct wseventvar *ev, stru else cnt = ev->put - ev->get; /* events in [get..put) */ splx(s); - n = howmany(uio->uio_resid, sizeof(struct wscons_event)); + n = howmany(uio->uio_resid, evsize); if (cnt > n) cnt = n; - error = uiomove(&ev->q[ev->get], - cnt * sizeof(struct wscons_event), uio); + error = wsevent_copyout_events(EVARRAY(ev, ev->get), cnt, uio, ver); n -= cnt; /* * If we do not wrap to 0, used up all our space, or had an error, @@ -237,8 +286,7 @@ wsevent_read(struct wseventvar *ev, stru return (error); if (cnt > n) cnt = n; - error = uiomove(&ev->q[0], - cnt * sizeof(struct wscons_event), uio); + error = wsevent_copyout_events(EVARRAY(ev, 0), cnt, uio, ver); ev->get = cnt; return (error); } @@ -282,10 +330,9 @@ filt_wseventread(struct knote *kn, long if (ev->get < ev->put) kn->kn_data = ev->put - ev->get; else - kn->kn_data = (WSEVENT_QSIZE - ev->get) + - ev->put; + kn->kn_data = (WSEVENT_QSIZE - ev->get) + ev->put; - kn->kn_data *= sizeof(struct wscons_event); + kn->kn_data *= EVSIZE(ev->version); return (1); } @@ -385,15 +432,36 @@ wsevent_inject(struct wseventvar *ev, st for (i = 0; i < nevents; i++) { struct wscons_event *we; - we = &ev->q[ev->put]; + we = EVARRAY(ev, ev->put); we->type = events[i].type; we->value = events[i].value; we->time = t; ev->put = (ev->put + 1) % WSEVENT_QSIZE; } - wsevent_wakeup(ev); return 0; } + +int +wsevent_setversion(struct wseventvar *ev, int vers) +{ + if (ev == NULL) + return EINVAL; + + switch (vers) { + case 0: + case WSEVENT_VERSION: + break; + default: + return EINVAL; + } + + if (vers == ev->version) + return 0; + + ev->get = ev->put = 0; + ev->version = vers; + return 0; +}