mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2025-12-25 22:20:06 +01:00
Add a general socket (not input device, but still need to be woken for it) handler to both the DIX and XFree86, and make XFree86's ACPI handling use it. This stops DPMS waking up every time an ACPI notification comes in.
186 lines
3.9 KiB
C
186 lines
3.9 KiB
C
#ifdef HAVE_XORG_CONFIG_H
|
|
#include "xorg-config.h"
|
|
#endif
|
|
|
|
#include "os.h"
|
|
#include "xf86.h"
|
|
#include "xf86Priv.h"
|
|
#define XF86_OS_PRIVS
|
|
#include "xf86_OSproc.h"
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#define ACPI_SOCKET "/var/run/acpid.socket"
|
|
|
|
#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
|
|
#define ACPI_VIDEO_NOTIFY_PROBE 0x81
|
|
#define ACPI_VIDEO_NOTIFY_CYCLE 0x82
|
|
#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
|
|
#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
|
|
|
|
#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82
|
|
#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83
|
|
#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84
|
|
#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
|
|
#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
|
|
|
|
#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
|
|
#define ACPI_VIDEO_HEAD_END (~0u)
|
|
|
|
static void lnxCloseACPI(void);
|
|
static pointer ACPIihPtr = NULL;
|
|
PMClose lnxACPIOpen(void);
|
|
|
|
/* in milliseconds */
|
|
#define ACPI_REOPEN_DELAY 1000
|
|
|
|
static CARD32
|
|
lnxACPIReopen(OsTimerPtr timer, CARD32 time, pointer arg)
|
|
{
|
|
if (lnxACPIOpen()) {
|
|
TimerFree(timer);
|
|
return 0;
|
|
}
|
|
|
|
return ACPI_REOPEN_DELAY;
|
|
}
|
|
|
|
#define LINE_LENGTH 80
|
|
|
|
static int
|
|
lnxACPIGetEventFromOs(int fd, pmEvent *events, int num)
|
|
{
|
|
char ev[LINE_LENGTH];
|
|
int n;
|
|
|
|
memset(ev, 0, LINE_LENGTH);
|
|
|
|
do {
|
|
n = read( fd, ev, LINE_LENGTH );
|
|
} while ((n == -1) && (errno == EAGAIN || errno == EINTR));
|
|
|
|
if (n <= 0) {
|
|
lnxCloseACPI();
|
|
TimerSet(NULL, 0, ACPI_REOPEN_DELAY, lnxACPIReopen, NULL);
|
|
return 0;
|
|
}
|
|
|
|
/* Check that we have a video event */
|
|
if (strstr(ev, "video") == ev) {
|
|
char *video = NULL;
|
|
char *GFX = NULL;
|
|
char *notify = NULL;
|
|
char *data = NULL; /* doesn't appear to be used in the kernel */
|
|
unsigned long int notify_l, data_l;
|
|
|
|
video = strtok(ev, "video");
|
|
|
|
GFX = strtok(NULL, " ");
|
|
#if 0
|
|
ErrorF("GFX: %s\n",GFX);
|
|
#endif
|
|
|
|
notify = strtok(NULL, " ");
|
|
notify_l = strtoul(notify, NULL, 16);
|
|
#if 0
|
|
ErrorF("notify: 0x%lx\n",notify_l);
|
|
#endif
|
|
|
|
data = strtok(NULL, " ");
|
|
data_l = strtoul(data, NULL, 16);
|
|
#if 0
|
|
ErrorF("data: 0x%lx\n",data_l);
|
|
#endif
|
|
|
|
/* We currently don't differentiate between any event */
|
|
switch (notify_l) {
|
|
case ACPI_VIDEO_NOTIFY_SWITCH:
|
|
break;
|
|
case ACPI_VIDEO_NOTIFY_PROBE:
|
|
break;
|
|
case ACPI_VIDEO_NOTIFY_CYCLE:
|
|
break;
|
|
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
|
|
break;
|
|
case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Deal with all ACPI events as a capability change */
|
|
events[0] = XF86_APM_CAPABILITY_CHANGED;
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static pmWait
|
|
lnxACPIConfirmEventToOs(int fd, pmEvent event)
|
|
{
|
|
/* No ability to send back to the kernel in ACPI */
|
|
switch (event) {
|
|
default:
|
|
return PM_NONE;
|
|
}
|
|
}
|
|
|
|
PMClose
|
|
lnxACPIOpen(void)
|
|
{
|
|
int fd;
|
|
struct sockaddr_un addr;
|
|
int r = -1;
|
|
|
|
#ifdef DEBUG
|
|
ErrorF("ACPI: OSPMOpen called\n");
|
|
#endif
|
|
if (ACPIihPtr || !xf86Info.pmFlag)
|
|
return NULL;
|
|
|
|
#ifdef DEBUG
|
|
ErrorF("ACPI: Opening device\n");
|
|
#endif
|
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) > -1) {
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.sun_family = AF_UNIX;
|
|
strcpy(addr.sun_path, ACPI_SOCKET);
|
|
if ((r = connect(fd, (struct sockaddr*)&addr, sizeof(addr))) == -1) {
|
|
xf86MsgVerb(X_WARNING,3,"Open ACPI failed (%s) (%s)\n", ACPI_SOCKET,
|
|
strerror(errno));
|
|
shutdown(fd, 2);
|
|
close(fd);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
xf86PMGetEventFromOs = lnxACPIGetEventFromOs;
|
|
xf86PMConfirmEventToOs = lnxACPIConfirmEventToOs;
|
|
ACPIihPtr = xf86AddGeneralHandler(fd,xf86HandlePMEvents,NULL);
|
|
xf86MsgVerb(X_INFO,3,"Open ACPI successful (%s)\n", ACPI_SOCKET);
|
|
|
|
return lnxCloseACPI;
|
|
}
|
|
|
|
static void
|
|
lnxCloseACPI(void)
|
|
{
|
|
int fd;
|
|
|
|
#ifdef DEBUG
|
|
ErrorF("ACPI: Closing device\n");
|
|
#endif
|
|
if (ACPIihPtr) {
|
|
fd = xf86RemoveGeneralHandler(ACPIihPtr);
|
|
shutdown(fd, 2);
|
|
close(fd);
|
|
ACPIihPtr = NULL;
|
|
}
|
|
}
|