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