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 void *ACPIihPtr = NULL; 37PMClose lnxACPIOpen(void); 38 39/* in milliseconds */ 40#define ACPI_REOPEN_DELAY 1000 41 42static CARD32 43lnxACPIReopen(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 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 *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 122static pmWait 123lnxACPIConfirmEventToOs(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 132PMClose 133lnxACPIOpen(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 169static void 170lnxCloseACPI(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