xserver-multidpi/hw/xfree86/os-support/bsd/bsd_apm.c
Adam Jackson c74220b853 APM: Use general handlers, not input handlers.
Otherwise APM events get treated as input events, which messes up idle
time accounting and screensavers and such.  Not, we hope, that anyone
is using APM anymore.
2009-03-30 14:56:15 -04:00

140 lines
3.2 KiB
C

#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <X11/X.h>
#include "os.h"
#include "xf86.h"
#include "xf86Priv.h"
#define XF86_OS_PRIVS
#include "xf86_OSproc.h"
#include "xf86_OSlib.h"
#include <machine/apmvar.h>
#define APM_DEVICE "/dev/apm"
static pointer APMihPtr = NULL;
static void bsdCloseAPM(void);
static struct {
u_int apmBsd;
pmEvent xf86;
} bsdToXF86Array [] = {
{ APM_STANDBY_REQ, XF86_APM_SYS_STANDBY },
{ APM_SUSPEND_REQ, XF86_APM_SYS_SUSPEND },
{ APM_NORMAL_RESUME, XF86_APM_NORMAL_RESUME },
{ APM_CRIT_RESUME, XF86_APM_CRITICAL_RESUME },
{ APM_BATTERY_LOW, XF86_APM_LOW_BATTERY },
{ APM_POWER_CHANGE, XF86_APM_POWER_STATUS_CHANGE },
{ APM_UPDATE_TIME, XF86_APM_UPDATE_TIME },
{ APM_CRIT_SUSPEND_REQ, XF86_APM_CRITICAL_SUSPEND },
{ APM_USER_STANDBY_REQ, XF86_APM_USER_STANDBY },
{ APM_USER_SUSPEND_REQ, XF86_APM_USER_SUSPEND },
{ APM_SYS_STANDBY_RESUME, XF86_APM_STANDBY_RESUME },
#ifdef APM_CAPABILITY_CHANGE
{ APM_CAPABILITY_CHANGE, XF86_APM_CAPABILITY_CHANGED },
#endif
};
#define numApmEvents (sizeof(bsdToXF86Array) / sizeof(bsdToXF86Array[0]))
static pmEvent
bsdToXF86(int type)
{
int i;
for (i = 0; i < numApmEvents; i++) {
if (type == bsdToXF86Array[i].apmBsd) {
return bsdToXF86Array[i].xf86;
}
}
return XF86_APM_UNKNOWN;
}
/*
* APM events can be requested direclty from /dev/apm
*/
static int
bsdPMGetEventFromOS(int fd, pmEvent *events, int num)
{
struct apm_event_info bsdEvent;
int i;
for (i = 0; i < num; i++) {
if (ioctl(fd, APM_IOC_NEXTEVENT, &bsdEvent) < 0) {
if (errno != EAGAIN) {
xf86Msg(X_WARNING, "bsdPMGetEventFromOS: APM_IOC_NEXTEVENT"
" %s\n", strerror(errno));
}
break;
}
events[i] = bsdToXF86(bsdEvent.type);
}
return i;
}
/*
* XXX This won't work on /dev/apm !
* We should either use /dev/apm_ctl (and kill apmd(8))
* or talk to apmd (but its protocol is not publically available)...
*/
static pmWait
bsdPMConfirmEventToOs(int fd, pmEvent event)
{
switch (event) {
case XF86_APM_SYS_STANDBY:
case XF86_APM_USER_STANDBY:
if (ioctl( fd, APM_IOC_STANDBY, NULL ) == 0)
return PM_WAIT; /* should we stop the Xserver in standby, too? */
else
return PM_NONE;
case XF86_APM_SYS_SUSPEND:
case XF86_APM_CRITICAL_SUSPEND:
case XF86_APM_USER_SUSPEND:
if (ioctl( fd, APM_IOC_SUSPEND, NULL ) == 0)
return PM_WAIT;
else
return PM_NONE;
case XF86_APM_STANDBY_RESUME:
case XF86_APM_NORMAL_RESUME:
case XF86_APM_CRITICAL_RESUME:
case XF86_APM_STANDBY_FAILED:
case XF86_APM_SUSPEND_FAILED:
return PM_CONTINUE;
default:
return PM_NONE;
}
}
PMClose
xf86OSPMOpen(void)
{
int fd;
if (APMihPtr || !xf86Info.pmFlag) {
return NULL;
}
if ((fd = open(APM_DEVICE, O_RDWR)) == -1) {
return NULL;
}
xf86PMGetEventFromOs = bsdPMGetEventFromOS;
xf86PMConfirmEventToOs = bsdPMConfirmEventToOs;
APMihPtr = xf86AddGeneralHandler(fd, xf86HandlePMEvents, NULL);
return bsdCloseAPM;
}
static void
bsdCloseAPM(void)
{
int fd;
if (APMihPtr) {
fd = xf86RemoveGeneralHandler(APMihPtr);
close(fd);
APMihPtr = NULL;
}
}