2 * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * Rickard E. (Rik) Faith <faith@redhat.com>
36 * Provides an interface for handling SIGIO signals for input devices. */
38 #ifdef HAVE_DMX_CONFIG_H
39 #include <dmx-config.h>
43 #include "dmxinputinit.h"
45 #include "dmxevents.h"
50 static int dmxFdCount
= 0;
51 static Bool dmxInputEnabled
= TRUE
;
53 /* Define equivalents for non-POSIX systems (e.g., SGI IRIX, Solaris) */
56 # define O_ASYNC FASYNC
62 #define O_NONBLOCK FNONBLK
65 static void dmxSigioHandler(int sig
)
68 DMXInputInfo
*dmxInput
;
70 for (i
= 0, dmxInput
= &dmxInputs
[0]; i
< dmxNumInputs
; i
++, dmxInput
++) {
71 if (dmxInput
->sigioState
== DMX_ACTIVESIGIO
) {
72 for (j
= 0; j
< dmxInput
->numDevs
; j
++) {
73 DMXLocalInputInfoPtr dmxLocal
= dmxInput
->devs
[j
];
74 if (dmxLocal
->collect_events
) {
75 dmxLocal
->collect_events(&dmxLocal
->pDevice
->public,
86 /** Block SIGIO handling. */
87 void dmxSigioBlock(void)
93 sigprocmask(SIG_BLOCK
, &s
, 0);
96 /** Unblock SIGIO handling. */
97 void dmxSigioUnblock(void)
102 sigaddset(&s
, SIGIO
);
103 sigprocmask(SIG_UNBLOCK
, &s
, 0);
106 static void dmxSigioHook(void)
111 memset(&a
, 0, sizeof(a
));
112 a
.sa_handler
= dmxSigioHandler
;
113 sigemptyset(&a
.sa_mask
);
114 sigaddset(&a
.sa_mask
, SIGIO
);
115 sigaddset(&a
.sa_mask
, SIGALRM
);
116 sigaddset(&a
.sa_mask
, SIGVTALRM
);
117 sigaction(SIGIO
, &a
, 0);
120 sigprocmask(SIG_SETMASK
, &s
, 0);
123 static void dmxSigioUnhook(void)
127 memset (&a
, 0, sizeof(a
));
128 a
.sa_handler
= SIG_IGN
;
129 sigemptyset(&a
.sa_mask
);
130 sigaction(SIGIO
, &a
, 0);
133 static void dmxSigioAdd(DMXInputInfo
*dmxInput
)
138 switch (dmxInput
->sigioState
) {
139 case DMX_NOSIGIO
: return;
140 case DMX_USESIGIO
: dmxInput
->sigioState
= DMX_ACTIVESIGIO
; break;
141 case DMX_ACTIVESIGIO
: return;
144 for (i
= 0; i
< dmxInput
->sigioFdCount
; i
++) {
145 if (!dmxInput
->sigioAdded
[i
]) {
146 int fd
= dmxInput
->sigioFd
[i
];
148 fcntl(fd
, F_SETOWN
, getpid());
149 flags
= fcntl(fd
, F_GETFL
);
150 flags
|= O_ASYNC
|O_NONBLOCK
;
151 fcntl(fd
, F_SETFL
, flags
);
153 AddEnabledDevice(fd
);
154 dmxInput
->sigioAdded
[i
] = TRUE
;
156 if (++dmxFdCount
== 1) dmxSigioHook();
161 static void dmxSigioRemove(DMXInputInfo
*dmxInput
)
166 switch (dmxInput
->sigioState
) {
167 case DMX_NOSIGIO
: return;
168 case DMX_USESIGIO
: return;
169 case DMX_ACTIVESIGIO
: dmxInput
->sigioState
= DMX_USESIGIO
; break;
172 for (i
= 0; i
< dmxInput
->sigioFdCount
; i
++) {
173 if (dmxInput
->sigioAdded
[i
]) {
174 int fd
= dmxInput
->sigioFd
[i
];
176 dmxInput
->sigioAdded
[i
] = FALSE
;
177 RemoveEnabledDevice(fd
);
179 flags
= fcntl(fd
, F_GETFL
);
180 flags
&= ~(O_ASYNC
|O_NONBLOCK
);
181 fcntl(fd
, F_SETFL
, flags
);
183 if (!--dmxFdCount
) dmxSigioUnhook();
188 /** Enable SIGIO handling. This instantiates the handler with the OS. */
189 void dmxSigioEnableInput(void)
192 DMXInputInfo
*dmxInput
;
194 dmxInputEnabled
= TRUE
;
195 for (i
= 0, dmxInput
= &dmxInputs
[0]; i
< dmxNumInputs
; i
++, dmxInput
++)
196 dmxSigioAdd(dmxInput
);
199 /** Disable SIGIO handling. This removes the hanlder from the OS. */
200 void dmxSigioDisableInput(void)
203 DMXInputInfo
*dmxInput
;
205 dmxInputEnabled
= FALSE
;
206 for (i
= 0, dmxInput
= &dmxInputs
[0]; i
< dmxNumInputs
; i
++, dmxInput
++)
207 dmxSigioRemove(dmxInput
);
210 /** Make a note that the input device described in \a dmxInput will be
211 * using the file descriptor \a fd for SIGIO signals. Calls
212 * AddEnabledDevice ifi SIGIO handling has been enabled with
213 * #dmxSigioEnableInput(). */
214 void dmxSigioRegister(DMXInputInfo
*dmxInput
, int fd
)
216 dmxInput
->sigioState
= DMX_USESIGIO
;
217 if (dmxInput
->sigioFdCount
>= DMX_MAX_SIGIO_FDS
)
218 dmxLog(dmxFatal
, "Too many SIGIO file descriptors (%d >= %d)\n",
219 dmxInput
->sigioFdCount
, DMX_MAX_SIGIO_FDS
);
221 dmxInput
->sigioFd
[dmxInput
->sigioFdCount
++] = fd
;
222 if (dmxInputEnabled
) dmxSigioAdd(dmxInput
);
225 /** Remove the notes that \a dmxInput is using any file descriptors for
226 * SIGIO signals. Calls RemoveEnabledDevice. */
227 void dmxSigioUnregister(DMXInputInfo
*dmxInput
)
229 if (dmxInput
->sigioState
== DMX_NOSIGIO
) return;
230 dmxSigioRemove(dmxInput
);
231 dmxInput
->sigioState
= DMX_NOSIGIO
;
232 dmxInput
->sigioFdCount
= 0;