Commit | Line | Data |
---|---|---|
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 | ||
35 | static void lnxCloseACPI(void); | |
36 | static pointer ACPIihPtr = NULL; | |
37 | PMClose lnxACPIOpen(void); | |
38 | ||
39 | /* in milliseconds */ | |
40 | #define ACPI_REOPEN_DELAY 1000 | |
41 | ||
42 | static CARD32 | |
43 | lnxACPIReopen(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 | ||
55 | static int | |
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 *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 | ||
123 | static pmWait | |
124 | lnxACPIConfirmEventToOs(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 | ||
133 | PMClose | |
134 | lnxACPIOpen(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 | ||
170 | static void | |
171 | lnxCloseACPI(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 | } |