1706f2543Smrg/* 2706f2543Smrg * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Authors: 30706f2543Smrg * Rickard E. (Rik) Faith <faith@redhat.com> 31706f2543Smrg * 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg/** \file 35706f2543Smrg * 36706f2543Smrg * Provides an interface for handling SIGIO signals for input devices. */ 37706f2543Smrg 38706f2543Smrg#ifdef HAVE_DMX_CONFIG_H 39706f2543Smrg#include <dmx-config.h> 40706f2543Smrg#endif 41706f2543Smrg 42706f2543Smrg#include "inputstr.h" 43706f2543Smrg#include "dmxinputinit.h" 44706f2543Smrg#include "dmxsigio.h" 45706f2543Smrg#include "dmxevents.h" 46706f2543Smrg#include <signal.h> 47706f2543Smrg#include <unistd.h> 48706f2543Smrg#include <fcntl.h> 49706f2543Smrg 50706f2543Smrgstatic int dmxFdCount = 0; 51706f2543Smrgstatic Bool dmxInputEnabled = TRUE; 52706f2543Smrg 53706f2543Smrg/* Define equivalents for non-POSIX systems (e.g., SGI IRIX, Solaris) */ 54706f2543Smrg#ifndef O_ASYNC 55706f2543Smrg# ifdef FASYNC 56706f2543Smrg# define O_ASYNC FASYNC 57706f2543Smrg# else 58706f2543Smrg# define O_ASYNC 0 59706f2543Smrg# endif 60706f2543Smrg#endif 61706f2543Smrg#ifndef O_NONBLOCK 62706f2543Smrg#define O_NONBLOCK FNONBLK 63706f2543Smrg#endif 64706f2543Smrg 65706f2543Smrgstatic void dmxSigioHandler(int sig) 66706f2543Smrg{ 67706f2543Smrg int i, j; 68706f2543Smrg DMXInputInfo *dmxInput; 69706f2543Smrg 70706f2543Smrg for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) { 71706f2543Smrg if (dmxInput->sigioState == DMX_ACTIVESIGIO) { 72706f2543Smrg for (j = 0; j < dmxInput->numDevs; j++) { 73706f2543Smrg DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j]; 74706f2543Smrg if (dmxLocal->collect_events) { 75706f2543Smrg dmxLocal->collect_events(&dmxLocal->pDevice->public, 76706f2543Smrg dmxMotion, 77706f2543Smrg dmxEnqueue, 78706f2543Smrg dmxCheckSpecialKeys, 79706f2543Smrg DMX_NO_BLOCK); 80706f2543Smrg } 81706f2543Smrg } 82706f2543Smrg } 83706f2543Smrg } 84706f2543Smrg} 85706f2543Smrg 86706f2543Smrg/** Block SIGIO handling. */ 87706f2543Smrgvoid dmxSigioBlock(void) 88706f2543Smrg{ 89706f2543Smrg sigset_t s; 90706f2543Smrg 91706f2543Smrg sigemptyset(&s); 92706f2543Smrg sigaddset(&s, SIGIO); 93706f2543Smrg sigprocmask(SIG_BLOCK, &s, 0); 94706f2543Smrg} 95706f2543Smrg 96706f2543Smrg/** Unblock SIGIO handling. */ 97706f2543Smrgvoid dmxSigioUnblock(void) 98706f2543Smrg{ 99706f2543Smrg sigset_t s; 100706f2543Smrg 101706f2543Smrg sigemptyset(&s); 102706f2543Smrg sigaddset(&s, SIGIO); 103706f2543Smrg sigprocmask(SIG_UNBLOCK, &s, 0); 104706f2543Smrg} 105706f2543Smrg 106706f2543Smrgstatic void dmxSigioHook(void) 107706f2543Smrg{ 108706f2543Smrg struct sigaction a; 109706f2543Smrg sigset_t s; 110706f2543Smrg 111706f2543Smrg memset(&a, 0, sizeof(a)); 112706f2543Smrg a.sa_handler = dmxSigioHandler; 113706f2543Smrg sigemptyset(&a.sa_mask); 114706f2543Smrg sigaddset(&a.sa_mask, SIGIO); 115706f2543Smrg sigaddset(&a.sa_mask, SIGALRM); 116706f2543Smrg sigaddset(&a.sa_mask, SIGVTALRM); 117706f2543Smrg sigaction(SIGIO, &a, 0); 118706f2543Smrg 119706f2543Smrg sigemptyset(&s); 120706f2543Smrg sigprocmask(SIG_SETMASK, &s, 0); 121706f2543Smrg} 122706f2543Smrg 123706f2543Smrgstatic void dmxSigioUnhook(void) 124706f2543Smrg{ 125706f2543Smrg struct sigaction a; 126706f2543Smrg 127706f2543Smrg memset (&a, 0, sizeof(a)); 128706f2543Smrg a.sa_handler = SIG_IGN; 129706f2543Smrg sigemptyset(&a.sa_mask); 130706f2543Smrg sigaction(SIGIO, &a, 0); 131706f2543Smrg} 132706f2543Smrg 133706f2543Smrgstatic void dmxSigioAdd(DMXInputInfo *dmxInput) 134706f2543Smrg{ 135706f2543Smrg int flags; 136706f2543Smrg int i; 137706f2543Smrg 138706f2543Smrg switch (dmxInput->sigioState) { 139706f2543Smrg case DMX_NOSIGIO: return; 140706f2543Smrg case DMX_USESIGIO: dmxInput->sigioState = DMX_ACTIVESIGIO; break; 141706f2543Smrg case DMX_ACTIVESIGIO: return; 142706f2543Smrg } 143706f2543Smrg 144706f2543Smrg for (i = 0; i < dmxInput->sigioFdCount; i++) { 145706f2543Smrg if (!dmxInput->sigioAdded[i]) { 146706f2543Smrg int fd = dmxInput->sigioFd[i]; 147706f2543Smrg 148706f2543Smrg fcntl(fd, F_SETOWN, getpid()); 149706f2543Smrg flags = fcntl(fd, F_GETFL); 150706f2543Smrg flags |= O_ASYNC|O_NONBLOCK; 151706f2543Smrg fcntl(fd, F_SETFL, flags); 152706f2543Smrg 153706f2543Smrg AddEnabledDevice(fd); 154706f2543Smrg dmxInput->sigioAdded[i] = TRUE; 155706f2543Smrg 156706f2543Smrg if (++dmxFdCount == 1) dmxSigioHook(); 157706f2543Smrg } 158706f2543Smrg } 159706f2543Smrg} 160706f2543Smrg 161706f2543Smrgstatic void dmxSigioRemove(DMXInputInfo *dmxInput) 162706f2543Smrg{ 163706f2543Smrg int flags; 164706f2543Smrg int i; 165706f2543Smrg 166706f2543Smrg switch (dmxInput->sigioState) { 167706f2543Smrg case DMX_NOSIGIO: return; 168706f2543Smrg case DMX_USESIGIO: return; 169706f2543Smrg case DMX_ACTIVESIGIO: dmxInput->sigioState = DMX_USESIGIO; break; 170706f2543Smrg } 171706f2543Smrg 172706f2543Smrg for (i = 0; i < dmxInput->sigioFdCount; i++) { 173706f2543Smrg if (dmxInput->sigioAdded[i]) { 174706f2543Smrg int fd = dmxInput->sigioFd[i]; 175706f2543Smrg 176706f2543Smrg dmxInput->sigioAdded[i] = FALSE; 177706f2543Smrg RemoveEnabledDevice(fd); 178706f2543Smrg 179706f2543Smrg flags = fcntl(fd, F_GETFL); 180706f2543Smrg flags &= ~(O_ASYNC|O_NONBLOCK); 181706f2543Smrg fcntl(fd, F_SETFL, flags); 182706f2543Smrg 183706f2543Smrg if (!--dmxFdCount) dmxSigioUnhook(); 184706f2543Smrg } 185706f2543Smrg } 186706f2543Smrg} 187706f2543Smrg 188706f2543Smrg/** Enable SIGIO handling. This instantiates the handler with the OS. */ 189706f2543Smrgvoid dmxSigioEnableInput(void) 190706f2543Smrg{ 191706f2543Smrg int i; 192706f2543Smrg DMXInputInfo *dmxInput; 193706f2543Smrg 194706f2543Smrg dmxInputEnabled = TRUE; 195706f2543Smrg for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) 196706f2543Smrg dmxSigioAdd(dmxInput); 197706f2543Smrg} 198706f2543Smrg 199706f2543Smrg/** Disable SIGIO handling. This removes the hanlder from the OS. */ 200706f2543Smrgvoid dmxSigioDisableInput(void) 201706f2543Smrg{ 202706f2543Smrg int i; 203706f2543Smrg DMXInputInfo *dmxInput; 204706f2543Smrg 205706f2543Smrg dmxInputEnabled = FALSE; 206706f2543Smrg for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) 207706f2543Smrg dmxSigioRemove(dmxInput); 208706f2543Smrg} 209706f2543Smrg 210706f2543Smrg/** Make a note that the input device described in \a dmxInput will be 211706f2543Smrg * using the file descriptor \a fd for SIGIO signals. Calls 212706f2543Smrg * AddEnabledDevice ifi SIGIO handling has been enabled with 213706f2543Smrg * #dmxSigioEnableInput(). */ 214706f2543Smrgvoid dmxSigioRegister(DMXInputInfo *dmxInput, int fd) 215706f2543Smrg{ 216706f2543Smrg dmxInput->sigioState = DMX_USESIGIO; 217706f2543Smrg if (dmxInput->sigioFdCount >= DMX_MAX_SIGIO_FDS) 218706f2543Smrg dmxLog(dmxFatal, "Too many SIGIO file descriptors (%d >= %d)\n", 219706f2543Smrg dmxInput->sigioFdCount, DMX_MAX_SIGIO_FDS); 220706f2543Smrg 221706f2543Smrg dmxInput->sigioFd[dmxInput->sigioFdCount++] = fd; 222706f2543Smrg if (dmxInputEnabled) dmxSigioAdd(dmxInput); 223706f2543Smrg} 224706f2543Smrg 225706f2543Smrg/** Remove the notes that \a dmxInput is using any file descriptors for 226706f2543Smrg * SIGIO signals. Calls RemoveEnabledDevice. */ 227706f2543Smrgvoid dmxSigioUnregister(DMXInputInfo *dmxInput) 228706f2543Smrg{ 229706f2543Smrg if (dmxInput->sigioState == DMX_NOSIGIO) return; 230706f2543Smrg dmxSigioRemove(dmxInput); 231706f2543Smrg dmxInput->sigioState = DMX_NOSIGIO; 232706f2543Smrg dmxInput->sigioFdCount = 0; 233706f2543Smrg} 234