xf86PM.c revision 4642e01f
1/* 2 * Copyright (c) 2000-2002 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 */ 27 28#ifdef HAVE_XORG_CONFIG_H 29#include <xorg-config.h> 30#endif 31 32#include <X11/X.h> 33#include "xf86.h" 34#include "xf86Priv.h" 35#include "xf86Xinput.h" 36 37int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num) = NULL; 38pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event) = NULL; 39 40static Bool suspended = FALSE; 41 42static int 43eventName(pmEvent event, char **str) 44{ 45 switch(event) { 46 case XF86_APM_SYS_STANDBY: *str="System Standby Request"; return 0; 47 case XF86_APM_SYS_SUSPEND: *str="System Suspend Request"; return 0; 48 case XF86_APM_CRITICAL_SUSPEND: *str="Critical Suspend"; return 0; 49 case XF86_APM_USER_STANDBY: *str="User System Standby Request"; return 0; 50 case XF86_APM_USER_SUSPEND: *str="User System Suspend Request"; return 0; 51 case XF86_APM_STANDBY_RESUME: *str="System Standby Resume"; return 0; 52 case XF86_APM_NORMAL_RESUME: *str="Normal Resume System"; return 0; 53 case XF86_APM_CRITICAL_RESUME: *str="Critical Resume System"; return 0; 54 case XF86_APM_LOW_BATTERY: *str="Battery Low"; return 3; 55 case XF86_APM_POWER_STATUS_CHANGE: *str="Power Status Change";return 3; 56 case XF86_APM_UPDATE_TIME: *str="Update Time";return 3; 57 case XF86_APM_CAPABILITY_CHANGED: *str="Capability Changed"; return 3; 58 case XF86_APM_STANDBY_FAILED: *str="Standby Request Failed"; return 0; 59 case XF86_APM_SUSPEND_FAILED: *str="Suspend Request Failed"; return 0; 60 default: *str="Unknown Event"; return 0; 61 } 62} 63 64static void 65suspend (pmEvent event, Bool undo) 66{ 67 int i; 68 InputInfoPtr pInfo; 69 70 xf86inSuspend = TRUE; 71 72 for (i = 0; i < xf86NumScreens; i++) { 73 xf86EnableAccess(xf86Screens[i]); 74 if (xf86Screens[i]->EnableDisableFBAccess) 75 (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE); 76 } 77 pInfo = xf86InputDevs; 78 while (pInfo) { 79 DisableDevice(pInfo->dev); 80 pInfo = pInfo->next; 81 } 82 xf86EnterServerState(SETUP); 83 for (i = 0; i < xf86NumScreens; i++) { 84 xf86EnableAccess(xf86Screens[i]); 85 if (xf86Screens[i]->PMEvent) 86 xf86Screens[i]->PMEvent(i,event,undo); 87 else { 88 xf86Screens[i]->LeaveVT(i, 0); 89 xf86Screens[i]->vtSema = FALSE; 90 } 91 } 92 xf86AccessLeave(); 93 xf86AccessLeaveState(); 94} 95 96static void 97resume(pmEvent event, Bool undo) 98{ 99 int i; 100 InputInfoPtr pInfo; 101 102 xf86AccessEnter(); 103 xf86EnterServerState(SETUP); 104 for (i = 0; i < xf86NumScreens; i++) { 105 xf86EnableAccess(xf86Screens[i]); 106 if (xf86Screens[i]->PMEvent) 107 xf86Screens[i]->PMEvent(i,event,undo); 108 else { 109 xf86Screens[i]->vtSema = TRUE; 110 xf86Screens[i]->EnterVT(i, 0); 111 } 112 } 113 xf86EnterServerState(OPERATING); 114 for (i = 0; i < xf86NumScreens; i++) { 115 xf86EnableAccess(xf86Screens[i]); 116 if (xf86Screens[i]->EnableDisableFBAccess) 117 (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE); 118 } 119 dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); 120 pInfo = xf86InputDevs; 121 while (pInfo) { 122 EnableDevice(pInfo->dev); 123 pInfo = pInfo->next; 124 } 125 xf86inSuspend = FALSE; 126} 127 128static void 129DoApmEvent(pmEvent event, Bool undo) 130{ 131 /* 132 * we leave that as a global function for now. I don't know if 133 * this might cause problems in the future. It is a global server 134 * variable therefore it needs to be in a server info structure 135 */ 136 int i, setup = 0; 137 138 switch(event) { 139#if 0 140 case XF86_APM_SYS_STANDBY: 141 case XF86_APM_USER_STANDBY: 142#endif 143 case XF86_APM_SYS_SUSPEND: 144 case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/ 145 case XF86_APM_USER_SUSPEND: 146 /* should we do this ? */ 147 if (!undo && !suspended) { 148 suspend(event,undo); 149 suspended = TRUE; 150 } else if (undo && suspended) { 151 resume(event,undo); 152 suspended = FALSE; 153 } 154 break; 155#if 0 156 case XF86_APM_STANDBY_RESUME: 157#endif 158 case XF86_APM_NORMAL_RESUME: 159 case XF86_APM_CRITICAL_RESUME: 160 if (suspended) { 161 resume(event,undo); 162 suspended = FALSE; 163 } 164 break; 165 default: 166 for (i = 0; i < xf86NumScreens; i++) { 167 if (xf86Screens[i]->PMEvent) { 168 if (!setup) xf86EnterServerState(SETUP); 169 setup = 1; 170 xf86EnableAccess(xf86Screens[i]); 171 xf86Screens[i]->PMEvent(i,event,undo); 172 } 173 } 174 if (setup) xf86EnterServerState(OPERATING); 175 break; 176 } 177} 178 179#define MAX_NO_EVENTS 8 180 181void 182xf86HandlePMEvents(int fd, pointer data) 183{ 184 pmEvent events[MAX_NO_EVENTS]; 185 int i,n; 186 Bool wait = FALSE; 187 188 if (!xf86PMGetEventFromOs) 189 return; 190 191 if ((n = xf86PMGetEventFromOs(fd,events,MAX_NO_EVENTS))) { 192 do { 193 for (i = 0; i < n; i++) { 194 char *str = NULL; 195 int verb = eventName(events[i],&str); 196 197 xf86MsgVerb(X_INFO,verb,"PM Event received: %s\n",str); 198 DoApmEvent(events[i],FALSE); 199 switch (xf86PMConfirmEventToOs(fd,events[i])) { 200 case PM_WAIT: 201 wait = TRUE; 202 break; 203 case PM_CONTINUE: 204 wait = FALSE; 205 break; 206 case PM_FAILED: 207 DoApmEvent(events[i],TRUE); 208 wait = FALSE; 209 break; 210 default: 211 break; 212 } 213 } 214 if (wait) 215 n = xf86PMGetEventFromOs(fd,events,MAX_NO_EVENTS); 216 else 217 break; 218 } while (1); 219 } 220} 221