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
35 static void lnxCloseACPI(void);
36 static void *ACPIihPtr = NULL;
37 PMClose lnxACPIOpen(void);
38
39 /* in milliseconds */
40 #define ACPI_REOPEN_DELAY 1000
41
42 static CARD32
lnxACPIReopen(OsTimerPtr timer,CARD32 time,void * arg)43 lnxACPIReopen(OsTimerPtr timer, CARD32 time, void *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
55 static int
lnxACPIGetEventFromOs(int fd,pmEvent * events,int num)56 lnxACPIGetEventFromOs(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 *GFX = NULL;
78 char *notify = NULL;
79 char *data = NULL; /* doesn't appear to be used in the kernel */
80 unsigned long int notify_l;
81
82 strtok(ev, " ");
83
84 if (!(GFX = strtok(NULL, " ")))
85 return 0;
86 #if 0
87 ErrorF("GFX: %s\n", GFX);
88 #endif
89
90 if (!(notify = strtok(NULL, " ")))
91 return 0;
92 notify_l = strtoul(notify, NULL, 16);
93 #if 0
94 ErrorF("notify: 0x%lx\n", notify_l);
95 #endif
96
97 if (!(data = strtok(NULL, " ")))
98 return 0;
99 #if 0
100 data_l = strtoul(data, NULL, 16);
101 ErrorF("data: 0x%lx\n", data_l);
102 #endif
103
104 /* Differentiate between events */
105 switch (notify_l) {
106 case ACPI_VIDEO_NOTIFY_SWITCH:
107 case ACPI_VIDEO_NOTIFY_CYCLE:
108 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
109 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
110 events[0] = XF86_APM_CAPABILITY_CHANGED;
111 return 1;
112 case ACPI_VIDEO_NOTIFY_PROBE:
113 return 0;
114 default:
115 return 0;
116 }
117 }
118
119 return 0;
120 }
121
122 static pmWait
lnxACPIConfirmEventToOs(int fd,pmEvent event)123 lnxACPIConfirmEventToOs(int fd, pmEvent event)
124 {
125 /* No ability to send back to the kernel in ACPI */
126 switch (event) {
127 default:
128 return PM_NONE;
129 }
130 }
131
132 PMClose
lnxACPIOpen(void)133 lnxACPIOpen(void)
134 {
135 int fd;
136 struct sockaddr_un addr;
137 int r = -1;
138 static int warned = 0;
139
140 DebugF("ACPI: OSPMOpen called\n");
141 if (ACPIihPtr || !xf86Info.pmFlag)
142 return NULL;
143
144 DebugF("ACPI: Opening device\n");
145 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) > -1) {
146 memset(&addr, 0, sizeof(addr));
147 addr.sun_family = AF_UNIX;
148 strcpy(addr.sun_path, ACPI_SOCKET);
149 if ((r = connect(fd, (struct sockaddr *) &addr, sizeof(addr))) == -1) {
150 if (!warned)
151 xf86MsgVerb(X_WARNING, 3, "Open ACPI failed (%s) (%s)\n",
152 ACPI_SOCKET, strerror(errno));
153 warned = 1;
154 shutdown(fd, 2);
155 close(fd);
156 return NULL;
157 }
158 }
159
160 xf86PMGetEventFromOs = lnxACPIGetEventFromOs;
161 xf86PMConfirmEventToOs = lnxACPIConfirmEventToOs;
162 ACPIihPtr = xf86AddGeneralHandler(fd, xf86HandlePMEvents, NULL);
163 xf86MsgVerb(X_INFO, 3, "Open ACPI successful (%s)\n", ACPI_SOCKET);
164 warned = 0;
165
166 return lnxCloseACPI;
167 }
168
169 static void
lnxCloseACPI(void)170 lnxCloseACPI(void)
171 {
172 int fd;
173
174 DebugF("ACPI: Closing device\n");
175 if (ACPIihPtr) {
176 fd = xf86RemoveGeneralHandler(ACPIihPtr);
177 shutdown(fd, 2);
178 close(fd);
179 ACPIihPtr = NULL;
180 }
181 }
182