1 2#ifdef HAVE_XORG_CONFIG_H 3#include <xorg-config.h> 4#endif 5 6#include <X11/X.h> 7#include "os.h" 8#include "xf86.h" 9#include "xf86Priv.h" 10#define XF86_OS_PRIVS 11#include "xf86_OSproc.h" 12 13#ifdef HAVE_ACPI 14extern PMClose lnxACPIOpen(void); 15#endif 16 17#ifdef HAVE_APM 18 19#include <linux/apm_bios.h> 20#include <unistd.h> 21#include <sys/ioctl.h> 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <fcntl.h> 25#include <errno.h> 26 27#define APM_PROC "/proc/apm" 28#define APM_DEVICE "/dev/apm_bios" 29 30#ifndef APM_STANDBY_FAILED 31# define APM_STANDBY_FAILED 0xf000 32#endif 33#ifndef APM_SUSPEND_FAILED 34# define APM_SUSPEND_FAILED 0xf001 35#endif 36 37static PMClose lnxAPMOpen(void); 38static void lnxCloseAPM(void); 39static pointer APMihPtr = NULL; 40 41static struct { 42 apm_event_t apmLinux; 43 pmEvent xf86; 44} LinuxToXF86[] = { 45 { APM_SYS_STANDBY, XF86_APM_SYS_STANDBY }, 46 { APM_SYS_SUSPEND, XF86_APM_SYS_SUSPEND }, 47 { APM_NORMAL_RESUME, XF86_APM_NORMAL_RESUME }, 48 { APM_CRITICAL_RESUME, XF86_APM_CRITICAL_RESUME }, 49 { APM_LOW_BATTERY, XF86_APM_LOW_BATTERY }, 50 { APM_POWER_STATUS_CHANGE, XF86_APM_POWER_STATUS_CHANGE }, 51 { APM_UPDATE_TIME, XF86_APM_UPDATE_TIME }, 52 { APM_CRITICAL_SUSPEND, XF86_APM_CRITICAL_SUSPEND }, 53 { APM_USER_STANDBY, XF86_APM_USER_STANDBY }, 54 { APM_USER_SUSPEND, XF86_APM_USER_SUSPEND }, 55 { APM_STANDBY_RESUME, XF86_APM_STANDBY_RESUME }, 56#if defined(APM_CAPABILITY_CHANGED) 57 { APM_CAPABILITY_CHANGED, XF86_CAPABILITY_CHANGED }, 58#endif 59#if 0 60 { APM_STANDBY_FAILED, XF86_APM_STANDBY_FAILED }, 61 { APM_SUSPEND_FAILED, XF86_APM_SUSPEND_FAILED } 62#endif 63}; 64 65#define numApmEvents (sizeof(LinuxToXF86) / sizeof(LinuxToXF86[0])) 66 67/* 68 * APM is still under construction. 69 * I'm not sure if the places where I initialize/deinitialize 70 * apm is correct. Also I don't know what to do in SETUP state. 71 * This depends if wakeup gets called in this situation, too. 72 * Also we need to check if the action that is taken on an 73 * event is reasonable. 74 */ 75static int 76lnxPMGetEventFromOs(int fd, pmEvent *events, int num) 77{ 78 int i,j,n; 79 apm_event_t linuxEvents[8]; 80 81 if ((n = read( fd, linuxEvents, num * sizeof(apm_event_t) )) == -1) 82 return 0; 83 n /= sizeof(apm_event_t); 84 if (n > num) 85 n = num; 86 for (i = 0; i < n; i++) { 87 for (j = 0; j < numApmEvents; j++) 88 if (LinuxToXF86[j].apmLinux == linuxEvents[i]) { 89 events[i] = LinuxToXF86[j].xf86; 90 break; 91 } 92 if (j == numApmEvents) 93 events[i] = XF86_APM_UNKNOWN; 94 } 95 return n; 96} 97 98static pmWait 99lnxPMConfirmEventToOs(int fd, pmEvent event) 100{ 101 switch (event) { 102 case XF86_APM_SYS_STANDBY: 103 case XF86_APM_USER_STANDBY: 104 if (ioctl( fd, APM_IOC_STANDBY, NULL )) 105 return PM_FAILED; 106 return PM_CONTINUE; 107 case XF86_APM_SYS_SUSPEND: 108 case XF86_APM_CRITICAL_SUSPEND: 109 case XF86_APM_USER_SUSPEND: 110 if (ioctl( fd, APM_IOC_SUSPEND, NULL )) { 111 /* I believe this is wrong (EE) 112 EBUSY is sent when a device refuses to be suspended. 113 In this case we still need to undo everything we have 114 done to suspend ourselves or we will stay in suspended 115 state forever. */ 116 if (errno == EBUSY) 117 return PM_CONTINUE; 118 else 119 return PM_FAILED; 120 } 121 return PM_CONTINUE; 122 case XF86_APM_STANDBY_RESUME: 123 case XF86_APM_NORMAL_RESUME: 124 case XF86_APM_CRITICAL_RESUME: 125 case XF86_APM_STANDBY_FAILED: 126 case XF86_APM_SUSPEND_FAILED: 127 return PM_CONTINUE; 128 default: 129 return PM_NONE; 130 } 131} 132 133#endif // HAVE_APM 134 135PMClose 136xf86OSPMOpen(void) 137{ 138 PMClose ret = NULL; 139 140#ifdef HAVE_ACPI 141 /* Favour ACPI over APM, but only when enabled */ 142 143 if (!xf86acpiDisableFlag) 144 ret = lnxACPIOpen(); 145 146 if (!ret) 147#endif 148#ifdef HAVE_APM 149 ret = lnxAPMOpen(); 150#endif 151 152 return ret; 153} 154 155#ifdef HAVE_APM 156 157static PMClose 158lnxAPMOpen(void) 159{ 160 int fd, pfd; 161 162 DebugF("APM: OSPMOpen called\n"); 163 if (APMihPtr || !xf86Info.pmFlag) 164 return NULL; 165 166 DebugF("APM: Opening device\n"); 167 if ((fd = open( APM_DEVICE, O_RDWR )) > -1) { 168 if (access( APM_PROC, R_OK ) || 169 ((pfd = open( APM_PROC, O_RDONLY)) == -1)) { 170 xf86MsgVerb(X_WARNING,3,"Cannot open APM (%s) (%s)\n", 171 APM_PROC, strerror(errno)); 172 close(fd); 173 return NULL; 174 } else 175 close(pfd); 176 xf86PMGetEventFromOs = lnxPMGetEventFromOs; 177 xf86PMConfirmEventToOs = lnxPMConfirmEventToOs; 178 APMihPtr = xf86AddGeneralHandler(fd, xf86HandlePMEvents, NULL); 179 xf86MsgVerb(X_INFO,3,"Open APM successful\n"); 180 return lnxCloseAPM; 181 } 182 return NULL; 183} 184 185static void 186lnxCloseAPM(void) 187{ 188 int fd; 189 190 DebugF("APM: Closing device\n"); 191 if (APMihPtr) { 192 fd = xf86RemoveGeneralHandler(APMihPtr); 193 close(fd); 194 APMihPtr = NULL; 195 } 196} 197 198#endif // HAVE_APM 199