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#include "xf86_OSproc.h" 37 38int (*xf86PMGetEventFromOs) (int fd, pmEvent * events, int num) = NULL; 39pmWait (*xf86PMConfirmEventToOs) (int fd, pmEvent event) = NULL; 40 41static Bool suspended = FALSE; 42 43static int 44eventName(pmEvent event, const char **str) 45{ 46 switch (event) { 47 case XF86_APM_SYS_STANDBY: 48 *str = "System Standby Request"; 49 return 0; 50 case XF86_APM_SYS_SUSPEND: 51 *str = "System Suspend Request"; 52 return 0; 53 case XF86_APM_CRITICAL_SUSPEND: 54 *str = "Critical Suspend"; 55 return 0; 56 case XF86_APM_USER_STANDBY: 57 *str = "User System Standby Request"; 58 return 0; 59 case XF86_APM_USER_SUSPEND: 60 *str = "User System Suspend Request"; 61 return 0; 62 case XF86_APM_STANDBY_RESUME: 63 *str = "System Standby Resume"; 64 return 0; 65 case XF86_APM_NORMAL_RESUME: 66 *str = "Normal Resume System"; 67 return 0; 68 case XF86_APM_CRITICAL_RESUME: 69 *str = "Critical Resume System"; 70 return 0; 71 case XF86_APM_LOW_BATTERY: 72 *str = "Battery Low"; 73 return 3; 74 case XF86_APM_POWER_STATUS_CHANGE: 75 *str = "Power Status Change"; 76 return 3; 77 case XF86_APM_UPDATE_TIME: 78 *str = "Update Time"; 79 return 3; 80 case XF86_APM_CAPABILITY_CHANGED: 81 *str = "Capability Changed"; 82 return 3; 83 case XF86_APM_STANDBY_FAILED: 84 *str = "Standby Request Failed"; 85 return 0; 86 case XF86_APM_SUSPEND_FAILED: 87 *str = "Suspend Request Failed"; 88 return 0; 89 default: 90 *str = "Unknown Event"; 91 return 0; 92 } 93} 94 95static void 96suspend(pmEvent event, Bool undo) 97{ 98 int i; 99 InputInfoPtr pInfo; 100 101 for (i = 0; i < xf86NumScreens; i++) { 102 if (xf86Screens[i]->EnableDisableFBAccess) 103 (*xf86Screens[i]->EnableDisableFBAccess) (xf86Screens[i], FALSE); 104 } 105 pInfo = xf86InputDevs; 106 while (pInfo) { 107 DisableDevice(pInfo->dev, TRUE); 108 pInfo = pInfo->next; 109 } 110 input_lock(); 111 for (i = 0; i < xf86NumScreens; i++) { 112 if (xf86Screens[i]->PMEvent) 113 xf86Screens[i]->PMEvent(xf86Screens[i], event, undo); 114 else { 115 xf86Screens[i]->LeaveVT(xf86Screens[i]); 116 xf86Screens[i]->vtSema = FALSE; 117 } 118 } 119} 120 121static void 122resume(pmEvent event, Bool undo) 123{ 124 int i; 125 InputInfoPtr pInfo; 126 127 for (i = 0; i < xf86NumScreens; i++) { 128 if (xf86Screens[i]->PMEvent) 129 xf86Screens[i]->PMEvent(xf86Screens[i], event, undo); 130 else { 131 xf86Screens[i]->vtSema = TRUE; 132 xf86Screens[i]->EnterVT(xf86Screens[i]); 133 } 134 } 135 input_unlock(); 136 for (i = 0; i < xf86NumScreens; i++) { 137 if (xf86Screens[i]->EnableDisableFBAccess) 138 (*xf86Screens[i]->EnableDisableFBAccess) (xf86Screens[i], TRUE); 139 } 140 dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); 141 pInfo = xf86InputDevs; 142 while (pInfo) { 143 EnableDevice(pInfo->dev, TRUE); 144 pInfo = pInfo->next; 145 } 146} 147 148static void 149DoApmEvent(pmEvent event, Bool undo) 150{ 151 int i; 152 153 switch (event) { 154#if 0 155 case XF86_APM_SYS_STANDBY: 156 case XF86_APM_USER_STANDBY: 157#endif 158 case XF86_APM_SYS_SUSPEND: 159 case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */ 160 case XF86_APM_USER_SUSPEND: 161 /* should we do this ? */ 162 if (!undo && !suspended) { 163 suspend(event, undo); 164 suspended = TRUE; 165 } 166 else if (undo && suspended) { 167 resume(event, undo); 168 suspended = FALSE; 169 } 170 break; 171#if 0 172 case XF86_APM_STANDBY_RESUME: 173#endif 174 case XF86_APM_NORMAL_RESUME: 175 case XF86_APM_CRITICAL_RESUME: 176 if (suspended) { 177 resume(event, undo); 178 suspended = FALSE; 179 } 180 break; 181 default: 182 input_lock(); 183 for (i = 0; i < xf86NumScreens; i++) { 184 if (xf86Screens[i]->PMEvent) { 185 xf86Screens[i]->PMEvent(xf86Screens[i], event, undo); 186 } 187 } 188 input_unlock(); 189 break; 190 } 191} 192 193#define MAX_NO_EVENTS 8 194 195void 196xf86HandlePMEvents(int fd, void *data) 197{ 198 pmEvent events[MAX_NO_EVENTS]; 199 int i, n; 200 Bool wait = FALSE; 201 202 if (!xf86PMGetEventFromOs) 203 return; 204 205 if ((n = xf86PMGetEventFromOs(fd, events, MAX_NO_EVENTS))) { 206 do { 207 for (i = 0; i < n; i++) { 208 const char *str = NULL; 209 int verb = eventName(events[i], &str); 210 211 xf86MsgVerb(X_INFO, verb, "PM Event received: %s\n", str); 212 DoApmEvent(events[i], FALSE); 213 switch (xf86PMConfirmEventToOs(fd, events[i])) { 214 case PM_WAIT: 215 wait = TRUE; 216 break; 217 case PM_CONTINUE: 218 wait = FALSE; 219 break; 220 case PM_FAILED: 221 DoApmEvent(events[i], TRUE); 222 wait = FALSE; 223 break; 224 default: 225 break; 226 } 227 } 228 if (wait) 229 n = xf86PMGetEventFromOs(fd, events, MAX_NO_EVENTS); 230 else 231 break; 232 } while (1); 233 } 234} 235