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