Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / linux / lnx_acpi.c
CommitLineData
a09e091a
JB
1#ifdef HAVE_XORG_CONFIG_H
2#include "xorg-config.h"
3#endif
4
5#include "os.h"
6#include "xf86.h"
7#include "xf86Priv.h"
8#define XF86_OS_PRIVS
9#include "xf86_OSproc.h"
10#include <sys/ioctl.h>
11#include <sys/types.h>
12#include <sys/socket.h>
13#include <sys/un.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <errno.h>
17
18#define ACPI_SOCKET "/var/run/acpid.socket"
19
20#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
21#define ACPI_VIDEO_NOTIFY_PROBE 0x81
22#define ACPI_VIDEO_NOTIFY_CYCLE 0x82
23#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
24#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
25
26#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85
27#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86
28#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
29#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
30#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
31
32#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
33#define ACPI_VIDEO_HEAD_END (~0u)
34
35static void lnxCloseACPI(void);
36static pointer ACPIihPtr = NULL;
37PMClose lnxACPIOpen(void);
38
39/* in milliseconds */
40#define ACPI_REOPEN_DELAY 1000
41
42static CARD32
43lnxACPIReopen(OsTimerPtr timer, CARD32 time, pointer arg)
44{
45 if (lnxACPIOpen()) {
46 TimerFree(timer);
47 return 0;
48 }
49
50 return ACPI_REOPEN_DELAY;
51}
52
53#define LINE_LENGTH 80
54
55static int
56lnxACPIGetEventFromOs(int fd, pmEvent * events, int num)
57{
58 char ev[LINE_LENGTH];
59 int n;
60
61 memset(ev, 0, LINE_LENGTH);
62
63 do {
64 n = read(fd, ev, LINE_LENGTH);
65 } while ((n == -1) && (errno == EAGAIN || errno == EINTR));
66
67 if (n <= 0) {
68 lnxCloseACPI();
69 TimerSet(NULL, 0, ACPI_REOPEN_DELAY, lnxACPIReopen, NULL);
70 return 0;
71 }
72 /* FIXME: this only processes the first read ACPI event & might break
73 * with interrupted reads. */
74
75 /* Check that we have a video event */
76 if (!strncmp(ev, "video", 5)) {
77 char *video = NULL;
78 char *GFX = NULL;
79 char *notify = NULL;
80 char *data = NULL; /* doesn't appear to be used in the kernel */
81 unsigned long int notify_l, data_l;
82
83 video = strtok(ev, " ");
84
85 if (!(GFX = strtok(NULL, " ")))
86 return 0;
87#if 0
88 ErrorF("GFX: %s\n", GFX);
89#endif
90
91 if (!(notify = strtok(NULL, " ")))
92 return 0;
93 notify_l = strtoul(notify, NULL, 16);
94#if 0
95 ErrorF("notify: 0x%lx\n", notify_l);
96#endif
97
98 if (!(data = strtok(NULL, " ")))
99 return 0;
100 data_l = strtoul(data, NULL, 16);
101#if 0
102 ErrorF("data: 0x%lx\n", data_l);
103#endif
104
105 /* Differentiate between events */
106 switch (notify_l) {
107 case ACPI_VIDEO_NOTIFY_SWITCH:
108 case ACPI_VIDEO_NOTIFY_CYCLE:
109 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
110 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
111 events[0] = XF86_APM_CAPABILITY_CHANGED;
112 return 1;
113 case ACPI_VIDEO_NOTIFY_PROBE:
114 return 0;
115 default:
116 return 0;
117 }
118 }
119
120 return 0;
121}
122
123static pmWait
124lnxACPIConfirmEventToOs(int fd, pmEvent event)
125{
126 /* No ability to send back to the kernel in ACPI */
127 switch (event) {
128 default:
129 return PM_NONE;
130 }
131}
132
133PMClose
134lnxACPIOpen(void)
135{
136 int fd;
137 struct sockaddr_un addr;
138 int r = -1;
139 static int warned = 0;
140
141 DebugF("ACPI: OSPMOpen called\n");
142 if (ACPIihPtr || !xf86Info.pmFlag)
143 return NULL;
144
145 DebugF("ACPI: Opening device\n");
146 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) > -1) {
147 memset(&addr, 0, sizeof(addr));
148 addr.sun_family = AF_UNIX;
149 strcpy(addr.sun_path, ACPI_SOCKET);
150 if ((r = connect(fd, (struct sockaddr *) &addr, sizeof(addr))) == -1) {
151 if (!warned)
152 xf86MsgVerb(X_WARNING, 3, "Open ACPI failed (%s) (%s)\n",
153 ACPI_SOCKET, strerror(errno));
154 warned = 1;
155 shutdown(fd, 2);
156 close(fd);
157 return NULL;
158 }
159 }
160
161 xf86PMGetEventFromOs = lnxACPIGetEventFromOs;
162 xf86PMConfirmEventToOs = lnxACPIConfirmEventToOs;
163 ACPIihPtr = xf86AddGeneralHandler(fd, xf86HandlePMEvents, NULL);
164 xf86MsgVerb(X_INFO, 3, "Open ACPI successful (%s)\n", ACPI_SOCKET);
165 warned = 0;
166
167 return lnxCloseACPI;
168}
169
170static void
171lnxCloseACPI(void)
172{
173 int fd;
174
175 DebugF("ACPI: Closing device\n");
176 if (ACPIihPtr) {
177 fd = xf86RemoveGeneralHandler(ACPIihPtr);
178 shutdown(fd, 2);
179 close(fd);
180 ACPIihPtr = NULL;
181 }
182}