Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / shared / sigio.c
CommitLineData
a09e091a
JB
1/* sigio.c -- Support for SIGIO handler installation and removal
2 * Created: Thu Jun 3 15:39:18 1999 by faith@precisioninsight.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
27 */
28/*
29 * Copyright (c) 2002 by The XFree86 Project, Inc.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
45 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
47 * OTHER DEALINGS IN THE SOFTWARE.
48 *
49 * Except as contained in this notice, the name of the copyright holder(s)
50 * and author(s) shall not be used in advertising or otherwise to promote
51 * the sale, use or other dealings in this Software without prior written
52 * authorization from the copyright holder(s) and author(s).
53 */
54
55#ifdef HAVE_XORG_CONFIG_H
56#include <xorg-config.h>
57#endif
58
59#include <X11/X.h>
60#include "xf86.h"
61#include "xf86Priv.h"
62#include "xf86_OSlib.h"
63#include "inputstr.h"
64
65#ifdef HAVE_STROPTS_H
66#include <stropts.h>
67#endif
68
69#ifdef MAXDEVICES
70/* MAXDEVICES represents the maximimum number of input devices usable
71 * at the same time plus one entry for DRM support.
72 */
73#define MAX_FUNCS (MAXDEVICES + 1)
74#else
75#define MAX_FUNCS 16
76#endif
77
78typedef struct _xf86SigIOFunc {
79 void (*f) (int, void *);
80 int fd;
81 void *closure;
82} Xf86SigIOFunc;
83
84static Xf86SigIOFunc xf86SigIOFuncs[MAX_FUNCS];
85static int xf86SigIOMax;
86static int xf86SigIOMaxFd;
87static fd_set xf86SigIOMask;
88
89/*
90 * SIGIO gives no way of discovering which fd signalled, select
91 * to discover
92 */
93static void
94xf86SIGIO(int sig)
95{
96 int i;
97 fd_set ready;
98 struct timeval to;
99 int save_errno = errno; /* do not clobber the global errno */
100 int r;
101
102 inSignalContext = TRUE;
103
104 ready = xf86SigIOMask;
105 to.tv_sec = 0;
106 to.tv_usec = 0;
107 SYSCALL(r = select(xf86SigIOMaxFd, &ready, 0, 0, &to));
108 for (i = 0; r > 0 && i < xf86SigIOMax; i++)
109 if (xf86SigIOFuncs[i].f && FD_ISSET(xf86SigIOFuncs[i].fd, &ready)) {
110 (*xf86SigIOFuncs[i].f) (xf86SigIOFuncs[i].fd,
111 xf86SigIOFuncs[i].closure);
112 r--;
113 }
114 if (r > 0) {
115 xf86Msg(X_ERROR, "SIGIO %d descriptors not handled\n", r);
116 }
117 /* restore global errno */
118 errno = save_errno;
119
120 inSignalContext = FALSE;
121}
122
123static int
124xf86IsPipe(int fd)
125{
126 struct stat buf;
127
128 if (fstat(fd, &buf) < 0)
129 return 0;
130 return S_ISFIFO(buf.st_mode);
131}
132
133int
134xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure)
135{
136 struct sigaction sa;
137 struct sigaction osa;
138 int i;
139 int installed = FALSE;
140
141 if (!xf86Info.useSIGIO)
142 return 0;
143
144 for (i = 0; i < MAX_FUNCS; i++) {
145 if (!xf86SigIOFuncs[i].f) {
146 if (xf86IsPipe(fd))
147 return 0;
148 OsBlockSIGIO();
149#ifdef O_ASYNC
150 if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC) == -1) {
151 xf86Msg(X_WARNING, "fcntl(%d, O_ASYNC): %s\n",
152 fd, strerror(errno));
153 }
154 else {
155 if (fcntl(fd, F_SETOWN, getpid()) == -1) {
156 xf86Msg(X_WARNING, "fcntl(%d, F_SETOWN): %s\n",
157 fd, strerror(errno));
158 }
159 else {
160 installed = TRUE;
161 }
162 }
163#endif
164#ifdef I_SETSIG /* System V Streams - used on Solaris for input devices */
165 if (!installed && isastream(fd)) {
166 if (ioctl(fd, I_SETSIG, S_INPUT | S_ERROR | S_HANGUP) == -1) {
167 xf86Msg(X_WARNING, "fcntl(%d, I_SETSIG): %s\n",
168 fd, strerror(errno));
169 }
170 else {
171 installed = TRUE;
172 }
173 }
174#endif
175 if (!installed) {
176 OsReleaseSIGIO();
177 return 0;
178 }
179 sigemptyset(&sa.sa_mask);
180 sigaddset(&sa.sa_mask, SIGIO);
181 sa.sa_flags = 0;
182 sa.sa_handler = xf86SIGIO;
183 sigaction(SIGIO, &sa, &osa);
184 xf86SigIOFuncs[i].fd = fd;
185 xf86SigIOFuncs[i].closure = closure;
186 xf86SigIOFuncs[i].f = f;
187 if (i >= xf86SigIOMax)
188 xf86SigIOMax = i + 1;
189 if (fd >= xf86SigIOMaxFd)
190 xf86SigIOMaxFd = fd + 1;
191 FD_SET(fd, &xf86SigIOMask);
192 OsReleaseSIGIO();
193 return 1;
194 }
195 /* Allow overwriting of the closure and callback */
196 else if (xf86SigIOFuncs[i].fd == fd) {
197 xf86SigIOFuncs[i].closure = closure;
198 xf86SigIOFuncs[i].f = f;
199 return 1;
200 }
201 }
202 return 0;
203}
204
205int
206xf86RemoveSIGIOHandler(int fd)
207{
208 struct sigaction sa;
209 struct sigaction osa;
210 int i;
211 int max;
212 int maxfd;
213 int ret;
214
215 if (!xf86Info.useSIGIO)
216 return 0;
217
218 max = 0;
219 maxfd = -1;
220 ret = 0;
221 for (i = 0; i < MAX_FUNCS; i++) {
222 if (xf86SigIOFuncs[i].f) {
223 if (xf86SigIOFuncs[i].fd == fd) {
224 xf86SigIOFuncs[i].f = 0;
225 xf86SigIOFuncs[i].fd = 0;
226 xf86SigIOFuncs[i].closure = 0;
227 FD_CLR(fd, &xf86SigIOMask);
228 ret = 1;
229 }
230 else {
231 max = i + 1;
232 if (xf86SigIOFuncs[i].fd >= maxfd)
233 maxfd = xf86SigIOFuncs[i].fd + 1;
234 }
235 }
236 }
237 if (ret) {
238#ifdef O_ASYNC
239 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_ASYNC);
240#endif
241#ifdef I_SETSIG
242 if (isastream(fd)) {
243 if (ioctl(fd, I_SETSIG, 0) == -1) {
244 xf86Msg(X_WARNING, "fcntl(%d, I_SETSIG, 0): %s\n",
245 fd, strerror(errno));
246 }
247 }
248#endif
249 xf86SigIOMax = max;
250 xf86SigIOMaxFd = maxfd;
251 if (!max) {
252 sigemptyset(&sa.sa_mask);
253 sigaddset(&sa.sa_mask, SIGIO);
254 sa.sa_flags = 0;
255 sa.sa_handler = SIG_IGN;
256 sigaction(SIGIO, &sa, &osa);
257 }
258 }
259 return ret;
260}
261
262int
263xf86BlockSIGIO(void)
264{
265 return OsBlockSIGIO();
266}
267
268void
269xf86UnblockSIGIO(int wasset)
270{
271 OsReleaseSIGIO();
272}
273
274void
275xf86AssertBlockedSIGIO(char *where)
276{
277 sigset_t set, old;
278
279 sigemptyset(&set);
280 sigprocmask(SIG_BLOCK, &set, &old);
281 if (!sigismember(&old, SIGIO))
282 xf86Msg(X_ERROR, "SIGIO not blocked at %s\n", where);
283}
284
285/* XXX This is a quick hack for the benefit of xf86SetSilkenMouse() */
286
287int
288xf86SIGIOSupported(void)
289{
290 return 1;
291}