summaryrefslogtreecommitdiff
path: root/hw/xfree86/os-support/bsd/bsd_apm.c
blob: feaed21a2a43abc91e9a72a88770a44e2a2ce826 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#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;
    }
}

_X_EXPORT 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 = xf86AddInputHandler(fd, xf86HandlePMEvents, NULL);
    return bsdCloseAPM;
}

static void
bsdCloseAPM(void)
{
    int fd;

    if (APMihPtr) {
	fd = xf86RemoveInputHandler(APMihPtr);
	close(fd);
	APMihPtr = NULL;
    }
}