Line data Source code
1 : /* $OpenBSD: wsevent.c,v 1.17 2017/04/11 14:43:49 dhill Exp $ */
2 : /* $NetBSD: wsevent.c,v 1.16 2003/08/07 16:31:29 agc Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. All advertising materials mentioning features or use of this software
16 : * must display the following acknowledgement:
17 : * This product includes software developed by Christopher G. Demetriou
18 : * for the NetBSD Project.
19 : * 4. The name of the author may not be used to endorse or promote products
20 : * derived from this software without specific prior written permission
21 : *
22 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 : */
33 :
34 : /*
35 : * Copyright (c) 1992, 1993
36 : * The Regents of the University of California. All rights reserved.
37 : *
38 : * This software was developed by the Computer Systems Engineering group
39 : * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
40 : * contributed to Berkeley.
41 : *
42 : * All advertising materials mentioning features or use of this software
43 : * must display the following acknowledgement:
44 : * This product includes software developed by the University of
45 : * California, Lawrence Berkeley Laboratory.
46 : *
47 : * Redistribution and use in source and binary forms, with or without
48 : * modification, are permitted provided that the following conditions
49 : * are met:
50 : * 1. Redistributions of source code must retain the above copyright
51 : * notice, this list of conditions and the following disclaimer.
52 : * 2. Redistributions in binary form must reproduce the above copyright
53 : * notice, this list of conditions and the following disclaimer in the
54 : * documentation and/or other materials provided with the distribution.
55 : * 3. Neither the name of the University nor the names of its contributors
56 : * may be used to endorse or promote products derived from this software
57 : * without specific prior written permission.
58 : *
59 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 : * SUCH DAMAGE.
70 : *
71 : * @(#)event.c 8.1 (Berkeley) 6/11/93
72 : */
73 :
74 : /*
75 : * Internal "wscons_event" queue interface for the keyboard and mouse drivers.
76 : */
77 :
78 : #include <sys/param.h>
79 : #include <sys/malloc.h>
80 : #include <sys/systm.h>
81 : #include <sys/vnode.h>
82 : #include <sys/selinfo.h>
83 : #include <sys/poll.h>
84 :
85 : #include <dev/wscons/wsconsio.h>
86 : #include <dev/wscons/wseventvar.h>
87 :
88 : void filt_wseventdetach(struct knote *);
89 : int filt_wseventread(struct knote *, long);
90 :
91 : const struct filterops wsevent_filtops = {
92 : 1,
93 : NULL,
94 : filt_wseventdetach,
95 : filt_wseventread
96 : };
97 :
98 : /*
99 : * Initialize a wscons_event queue.
100 : */
101 : void
102 0 : wsevent_init(struct wseventvar *ev)
103 : {
104 :
105 0 : if (ev->q != NULL) {
106 : #ifdef DIAGNOSTIC
107 0 : printf("wsevent_init: already initialized\n");
108 : #endif
109 0 : return;
110 : }
111 0 : ev->get = ev->put = 0;
112 0 : ev->q = malloc(WSEVENT_QSIZE * sizeof(struct wscons_event),
113 : M_DEVBUF, M_WAITOK | M_ZERO);
114 0 : }
115 :
116 : /*
117 : * Tear down a wscons_event queue.
118 : */
119 : void
120 0 : wsevent_fini(struct wseventvar *ev)
121 : {
122 0 : if (ev->q == NULL) {
123 : #ifdef DIAGNOSTIC
124 0 : printf("wsevent_fini: already invoked\n");
125 : #endif
126 0 : return;
127 : }
128 0 : free(ev->q, M_DEVBUF, 0);
129 0 : ev->q = NULL;
130 0 : }
131 :
132 : /*
133 : * User-level interface: read, poll.
134 : * (User cannot write an event queue.)
135 : */
136 : int
137 0 : wsevent_read(struct wseventvar *ev, struct uio *uio, int flags)
138 : {
139 : int s, error;
140 : u_int cnt;
141 : size_t n;
142 :
143 : /*
144 : * Make sure we can return at least 1.
145 : */
146 0 : if (uio->uio_resid < sizeof(struct wscons_event))
147 0 : return (EMSGSIZE); /* ??? */
148 0 : s = splwsevent();
149 0 : while (ev->get == ev->put) {
150 0 : if (flags & IO_NDELAY) {
151 0 : splx(s);
152 0 : return (EWOULDBLOCK);
153 : }
154 0 : ev->wanted = 1;
155 0 : error = tsleep(ev, PWSEVENT | PCATCH,
156 : "wsevent_read", 0);
157 0 : if (error) {
158 0 : splx(s);
159 0 : return (error);
160 : }
161 : }
162 : /*
163 : * Move wscons_event from tail end of queue (there is at least one
164 : * there).
165 : */
166 0 : if (ev->put < ev->get)
167 0 : cnt = WSEVENT_QSIZE - ev->get; /* events in [get..QSIZE) */
168 : else
169 0 : cnt = ev->put - ev->get; /* events in [get..put) */
170 0 : splx(s);
171 0 : n = howmany(uio->uio_resid, sizeof(struct wscons_event));
172 0 : if (cnt > n)
173 0 : cnt = n;
174 0 : error = uiomove((caddr_t)&ev->q[ev->get],
175 0 : cnt * sizeof(struct wscons_event), uio);
176 0 : n -= cnt;
177 : /*
178 : * If we do not wrap to 0, used up all our space, or had an error,
179 : * stop. Otherwise move from front of queue to put index, if there
180 : * is anything there to move.
181 : */
182 0 : if ((ev->get = (ev->get + cnt) % WSEVENT_QSIZE) != 0 ||
183 0 : n == 0 || error || (cnt = ev->put) == 0)
184 0 : return (error);
185 0 : if (cnt > n)
186 0 : cnt = n;
187 0 : error = uiomove((caddr_t)&ev->q[0],
188 0 : cnt * sizeof(struct wscons_event), uio);
189 0 : ev->get = cnt;
190 0 : return (error);
191 0 : }
192 :
193 : int
194 0 : wsevent_poll(struct wseventvar *ev, int events, struct proc *p)
195 : {
196 : int revents = 0;
197 0 : int s = splwsevent();
198 :
199 0 : if (events & (POLLIN | POLLRDNORM)) {
200 0 : if (ev->get != ev->put)
201 0 : revents |= events & (POLLIN | POLLRDNORM);
202 : else
203 0 : selrecord(p, &ev->sel);
204 : }
205 :
206 0 : splx(s);
207 0 : return (revents);
208 : }
209 :
210 : int
211 0 : wsevent_kqfilter(struct wseventvar *ev, struct knote *kn)
212 : {
213 : struct klist *klist;
214 : int s;
215 :
216 0 : klist = &ev->sel.si_note;
217 :
218 0 : switch (kn->kn_filter) {
219 : case EVFILT_READ:
220 0 : kn->kn_fop = &wsevent_filtops;
221 : break;
222 : default:
223 0 : return (EINVAL);
224 : }
225 :
226 0 : kn->kn_hook = ev;
227 :
228 0 : s = splwsevent();
229 0 : SLIST_INSERT_HEAD(klist, kn, kn_selnext);
230 0 : splx(s);
231 :
232 0 : return (0);
233 0 : }
234 :
235 : void
236 0 : filt_wseventdetach(struct knote *kn)
237 : {
238 0 : struct wseventvar *ev = kn->kn_hook;
239 0 : struct klist *klist = &ev->sel.si_note;
240 : int s;
241 :
242 0 : s = splwsevent();
243 0 : SLIST_REMOVE(klist, kn, knote, kn_selnext);
244 0 : splx(s);
245 0 : }
246 :
247 : int
248 0 : filt_wseventread(struct knote *kn, long hint)
249 : {
250 0 : struct wseventvar *ev = kn->kn_hook;
251 :
252 0 : if (ev->get == ev->put)
253 0 : return (0);
254 :
255 0 : if (ev->get < ev->put)
256 0 : kn->kn_data = ev->put - ev->get;
257 : else
258 0 : kn->kn_data = (WSEVENT_QSIZE - ev->get) + ev->put;
259 :
260 0 : return (1);
261 0 : }
|