1/***************************************************************** 2 3Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts. 4 5Permission is hereby granted, free of charge, to any person obtaining a copy 6of this software and associated documentation files (the "Software"), to deal 7in the Software without restriction, including without limitation the rights 8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9copies of the Software. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 18BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 19WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 20IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of Digital Equipment Corporation 23shall not be used in advertising or otherwise to promote the sale, use or other 24dealings in this Software without prior written authorization from Digital 25Equipment Corporation. 26 27******************************************************************/ 28 29#ifdef HAVE_DIX_CONFIG_H 30#include <dix-config.h> 31#endif 32 33#include <X11/X.h> 34#include <X11/Xproto.h> 35#include "misc.h" 36#include "os.h" 37#include "dixstruct.h" 38#include "extnsionst.h" 39#include "opaque.h" 40#include <X11/extensions/dpmsproto.h> 41#include "dpmsproc.h" 42#include "extinit.h" 43#include "scrnintstr.h" 44#include "windowstr.h" 45 46CARD16 DPMSPowerLevel = 0; 47Bool DPMSDisabledSwitch = FALSE; 48CARD32 DPMSStandbyTime = -1; 49CARD32 DPMSSuspendTime = -1; 50CARD32 DPMSOffTime = -1; 51Bool DPMSEnabled; 52 53Bool 54DPMSSupported(void) 55{ 56 int i; 57 58 /* For each screen, check if DPMS is supported */ 59 for (i = 0; i < screenInfo.numScreens; i++) 60 if (screenInfo.screens[i]->DPMS != NULL) 61 return TRUE; 62 63 for (i = 0; i < screenInfo.numGPUScreens; i++) 64 if (screenInfo.gpuscreens[i]->DPMS != NULL) 65 return TRUE; 66 67 return FALSE; 68} 69 70static Bool 71isUnblank(int mode) 72{ 73 switch (mode) { 74 case SCREEN_SAVER_OFF: 75 case SCREEN_SAVER_FORCER: 76 return TRUE; 77 case SCREEN_SAVER_ON: 78 case SCREEN_SAVER_CYCLE: 79 return FALSE; 80 default: 81 return TRUE; 82 } 83} 84 85int 86DPMSSet(ClientPtr client, int level) 87{ 88 int rc, i; 89 90 DPMSPowerLevel = level; 91 92 if (level != DPMSModeOn) { 93 if (isUnblank(screenIsSaved)) { 94 rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); 95 if (rc != Success) 96 return rc; 97 } 98 } else if (!isUnblank(screenIsSaved)) { 99 rc = dixSaveScreens(client, SCREEN_SAVER_OFF, ScreenSaverReset); 100 if (rc != Success) 101 return rc; 102 } 103 104 for (i = 0; i < screenInfo.numScreens; i++) 105 if (screenInfo.screens[i]->DPMS != NULL) 106 screenInfo.screens[i]->DPMS(screenInfo.screens[i], level); 107 108 for (i = 0; i < screenInfo.numGPUScreens; i++) 109 if (screenInfo.gpuscreens[i]->DPMS != NULL) 110 screenInfo.gpuscreens[i]->DPMS(screenInfo.gpuscreens[i], level); 111 112 return Success; 113} 114 115static int 116ProcDPMSGetVersion(ClientPtr client) 117{ 118 /* REQUEST(xDPMSGetVersionReq); */ 119 xDPMSGetVersionReply rep = { 120 .type = X_Reply, 121 .sequenceNumber = client->sequence, 122 .length = 0, 123 .majorVersion = DPMSMajorVersion, 124 .minorVersion = DPMSMinorVersion 125 }; 126 127 REQUEST_SIZE_MATCH(xDPMSGetVersionReq); 128 129 if (client->swapped) { 130 swaps(&rep.sequenceNumber); 131 swaps(&rep.majorVersion); 132 swaps(&rep.minorVersion); 133 } 134 WriteToClient(client, sizeof(xDPMSGetVersionReply), &rep); 135 return Success; 136} 137 138static int 139ProcDPMSCapable(ClientPtr client) 140{ 141 /* REQUEST(xDPMSCapableReq); */ 142 xDPMSCapableReply rep = { 143 .type = X_Reply, 144 .sequenceNumber = client->sequence, 145 .length = 0, 146 .capable = TRUE 147 }; 148 149 REQUEST_SIZE_MATCH(xDPMSCapableReq); 150 151 if (client->swapped) { 152 swaps(&rep.sequenceNumber); 153 } 154 WriteToClient(client, sizeof(xDPMSCapableReply), &rep); 155 return Success; 156} 157 158static int 159ProcDPMSGetTimeouts(ClientPtr client) 160{ 161 /* REQUEST(xDPMSGetTimeoutsReq); */ 162 xDPMSGetTimeoutsReply rep = { 163 .type = X_Reply, 164 .sequenceNumber = client->sequence, 165 .length = 0, 166 .standby = DPMSStandbyTime / MILLI_PER_SECOND, 167 .suspend = DPMSSuspendTime / MILLI_PER_SECOND, 168 .off = DPMSOffTime / MILLI_PER_SECOND 169 }; 170 171 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); 172 173 if (client->swapped) { 174 swaps(&rep.sequenceNumber); 175 swaps(&rep.standby); 176 swaps(&rep.suspend); 177 swaps(&rep.off); 178 } 179 WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), &rep); 180 return Success; 181} 182 183static int 184ProcDPMSSetTimeouts(ClientPtr client) 185{ 186 REQUEST(xDPMSSetTimeoutsReq); 187 188 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); 189 190 if ((stuff->off != 0) && (stuff->off < stuff->suspend)) { 191 client->errorValue = stuff->off; 192 return BadValue; 193 } 194 if ((stuff->suspend != 0) && (stuff->suspend < stuff->standby)) { 195 client->errorValue = stuff->suspend; 196 return BadValue; 197 } 198 199 DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND; 200 DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND; 201 DPMSOffTime = stuff->off * MILLI_PER_SECOND; 202 SetScreenSaverTimer(); 203 204 return Success; 205} 206 207static int 208ProcDPMSEnable(ClientPtr client) 209{ 210 Bool was_enabled = DPMSEnabled; 211 212 REQUEST_SIZE_MATCH(xDPMSEnableReq); 213 214 DPMSEnabled = TRUE; 215 if (!was_enabled) 216 SetScreenSaverTimer(); 217 218 return Success; 219} 220 221static int 222ProcDPMSDisable(ClientPtr client) 223{ 224 /* REQUEST(xDPMSDisableReq); */ 225 226 REQUEST_SIZE_MATCH(xDPMSDisableReq); 227 228 DPMSSet(client, DPMSModeOn); 229 230 DPMSEnabled = FALSE; 231 232 return Success; 233} 234 235static int 236ProcDPMSForceLevel(ClientPtr client) 237{ 238 REQUEST(xDPMSForceLevelReq); 239 240 REQUEST_SIZE_MATCH(xDPMSForceLevelReq); 241 242 if (!DPMSEnabled) 243 return BadMatch; 244 245 if (stuff->level != DPMSModeOn && 246 stuff->level != DPMSModeStandby && 247 stuff->level != DPMSModeSuspend && stuff->level != DPMSModeOff) { 248 client->errorValue = stuff->level; 249 return BadValue; 250 } 251 252 DPMSSet(client, stuff->level); 253 254 return Success; 255} 256 257static int 258ProcDPMSInfo(ClientPtr client) 259{ 260 /* REQUEST(xDPMSInfoReq); */ 261 xDPMSInfoReply rep = { 262 .type = X_Reply, 263 .sequenceNumber = client->sequence, 264 .length = 0, 265 .power_level = DPMSPowerLevel, 266 .state = DPMSEnabled 267 }; 268 269 REQUEST_SIZE_MATCH(xDPMSInfoReq); 270 271 if (client->swapped) { 272 swaps(&rep.sequenceNumber); 273 swaps(&rep.power_level); 274 } 275 WriteToClient(client, sizeof(xDPMSInfoReply), &rep); 276 return Success; 277} 278 279static int 280ProcDPMSDispatch(ClientPtr client) 281{ 282 REQUEST(xReq); 283 284 switch (stuff->data) { 285 case X_DPMSGetVersion: 286 return ProcDPMSGetVersion(client); 287 case X_DPMSCapable: 288 return ProcDPMSCapable(client); 289 case X_DPMSGetTimeouts: 290 return ProcDPMSGetTimeouts(client); 291 case X_DPMSSetTimeouts: 292 return ProcDPMSSetTimeouts(client); 293 case X_DPMSEnable: 294 return ProcDPMSEnable(client); 295 case X_DPMSDisable: 296 return ProcDPMSDisable(client); 297 case X_DPMSForceLevel: 298 return ProcDPMSForceLevel(client); 299 case X_DPMSInfo: 300 return ProcDPMSInfo(client); 301 default: 302 return BadRequest; 303 } 304} 305 306static int _X_COLD 307SProcDPMSGetVersion(ClientPtr client) 308{ 309 REQUEST(xDPMSGetVersionReq); 310 311 swaps(&stuff->length); 312 REQUEST_SIZE_MATCH(xDPMSGetVersionReq); 313 swaps(&stuff->majorVersion); 314 swaps(&stuff->minorVersion); 315 return ProcDPMSGetVersion(client); 316} 317 318static int _X_COLD 319SProcDPMSCapable(ClientPtr client) 320{ 321 REQUEST(xDPMSCapableReq); 322 323 swaps(&stuff->length); 324 REQUEST_SIZE_MATCH(xDPMSCapableReq); 325 326 return ProcDPMSCapable(client); 327} 328 329static int _X_COLD 330SProcDPMSGetTimeouts(ClientPtr client) 331{ 332 REQUEST(xDPMSGetTimeoutsReq); 333 334 swaps(&stuff->length); 335 REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); 336 337 return ProcDPMSGetTimeouts(client); 338} 339 340static int _X_COLD 341SProcDPMSSetTimeouts(ClientPtr client) 342{ 343 REQUEST(xDPMSSetTimeoutsReq); 344 345 swaps(&stuff->length); 346 REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); 347 348 swaps(&stuff->standby); 349 swaps(&stuff->suspend); 350 swaps(&stuff->off); 351 return ProcDPMSSetTimeouts(client); 352} 353 354static int _X_COLD 355SProcDPMSEnable(ClientPtr client) 356{ 357 REQUEST(xDPMSEnableReq); 358 359 swaps(&stuff->length); 360 REQUEST_SIZE_MATCH(xDPMSEnableReq); 361 362 return ProcDPMSEnable(client); 363} 364 365static int _X_COLD 366SProcDPMSDisable(ClientPtr client) 367{ 368 REQUEST(xDPMSDisableReq); 369 370 swaps(&stuff->length); 371 REQUEST_SIZE_MATCH(xDPMSDisableReq); 372 373 return ProcDPMSDisable(client); 374} 375 376static int _X_COLD 377SProcDPMSForceLevel(ClientPtr client) 378{ 379 REQUEST(xDPMSForceLevelReq); 380 381 swaps(&stuff->length); 382 REQUEST_SIZE_MATCH(xDPMSForceLevelReq); 383 384 swaps(&stuff->level); 385 386 return ProcDPMSForceLevel(client); 387} 388 389static int _X_COLD 390SProcDPMSInfo(ClientPtr client) 391{ 392 REQUEST(xDPMSInfoReq); 393 394 swaps(&stuff->length); 395 REQUEST_SIZE_MATCH(xDPMSInfoReq); 396 397 return ProcDPMSInfo(client); 398} 399 400static int _X_COLD 401SProcDPMSDispatch(ClientPtr client) 402{ 403 REQUEST(xReq); 404 switch (stuff->data) { 405 case X_DPMSGetVersion: 406 return SProcDPMSGetVersion(client); 407 case X_DPMSCapable: 408 return SProcDPMSCapable(client); 409 case X_DPMSGetTimeouts: 410 return SProcDPMSGetTimeouts(client); 411 case X_DPMSSetTimeouts: 412 return SProcDPMSSetTimeouts(client); 413 case X_DPMSEnable: 414 return SProcDPMSEnable(client); 415 case X_DPMSDisable: 416 return SProcDPMSDisable(client); 417 case X_DPMSForceLevel: 418 return SProcDPMSForceLevel(client); 419 case X_DPMSInfo: 420 return SProcDPMSInfo(client); 421 default: 422 return BadRequest; 423 } 424} 425 426static void 427DPMSCloseDownExtension(ExtensionEntry *e) 428{ 429 DPMSSet(serverClient, DPMSModeOn); 430} 431 432void 433DPMSExtensionInit(void) 434{ 435#define CONDITIONALLY_SET_DPMS_TIMEOUT(_timeout_value_) \ 436 if (_timeout_value_ == -1) { /* not yet set from config */ \ 437 _timeout_value_ = ScreenSaverTime; \ 438 } 439 440 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSStandbyTime) 441 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSSuspendTime) 442 CONDITIONALLY_SET_DPMS_TIMEOUT(DPMSOffTime) 443 444 DPMSPowerLevel = DPMSModeOn; 445 DPMSEnabled = DPMSSupported(); 446 447 if (DPMSEnabled) 448 AddExtension(DPMSExtensionName, 0, 0, 449 ProcDPMSDispatch, SProcDPMSDispatch, 450 DPMSCloseDownExtension, StandardMinorOpcode); 451} 452