1 /*****************************************************************
2 
3 Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software.
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 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
18 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
19 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
20 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of Digital Equipment Corporation
23 shall not be used in advertising or otherwise to promote the sale, use or other
24 dealings in this Software without prior written authorization from Digital
25 Equipment 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 
46 CARD16 DPMSPowerLevel = 0;
47 Bool DPMSDisabledSwitch = FALSE;
48 CARD32 DPMSStandbyTime = -1;
49 CARD32 DPMSSuspendTime = -1;
50 CARD32 DPMSOffTime = -1;
51 Bool DPMSEnabled;
52 
53 Bool
DPMSSupported(void)54 DPMSSupported(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 
70 static Bool
isUnblank(int mode)71 isUnblank(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 
85 int
DPMSSet(ClientPtr client,int level)86 DPMSSet(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 
115 static int
ProcDPMSGetVersion(ClientPtr client)116 ProcDPMSGetVersion(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 
138 static int
ProcDPMSCapable(ClientPtr client)139 ProcDPMSCapable(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 
158 static int
ProcDPMSGetTimeouts(ClientPtr client)159 ProcDPMSGetTimeouts(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 
183 static int
ProcDPMSSetTimeouts(ClientPtr client)184 ProcDPMSSetTimeouts(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 
207 static int
ProcDPMSEnable(ClientPtr client)208 ProcDPMSEnable(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 
221 static int
ProcDPMSDisable(ClientPtr client)222 ProcDPMSDisable(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 
235 static int
ProcDPMSForceLevel(ClientPtr client)236 ProcDPMSForceLevel(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 
257 static int
ProcDPMSInfo(ClientPtr client)258 ProcDPMSInfo(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 
279 static int
ProcDPMSDispatch(ClientPtr client)280 ProcDPMSDispatch(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 
306 static int _X_COLD
SProcDPMSGetVersion(ClientPtr client)307 SProcDPMSGetVersion(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 
318 static int _X_COLD
SProcDPMSCapable(ClientPtr client)319 SProcDPMSCapable(ClientPtr client)
320 {
321     REQUEST(xDPMSCapableReq);
322 
323     swaps(&stuff->length);
324     REQUEST_SIZE_MATCH(xDPMSCapableReq);
325 
326     return ProcDPMSCapable(client);
327 }
328 
329 static int _X_COLD
SProcDPMSGetTimeouts(ClientPtr client)330 SProcDPMSGetTimeouts(ClientPtr client)
331 {
332     REQUEST(xDPMSGetTimeoutsReq);
333 
334     swaps(&stuff->length);
335     REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
336 
337     return ProcDPMSGetTimeouts(client);
338 }
339 
340 static int _X_COLD
SProcDPMSSetTimeouts(ClientPtr client)341 SProcDPMSSetTimeouts(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 
354 static int _X_COLD
SProcDPMSEnable(ClientPtr client)355 SProcDPMSEnable(ClientPtr client)
356 {
357     REQUEST(xDPMSEnableReq);
358 
359     swaps(&stuff->length);
360     REQUEST_SIZE_MATCH(xDPMSEnableReq);
361 
362     return ProcDPMSEnable(client);
363 }
364 
365 static int _X_COLD
SProcDPMSDisable(ClientPtr client)366 SProcDPMSDisable(ClientPtr client)
367 {
368     REQUEST(xDPMSDisableReq);
369 
370     swaps(&stuff->length);
371     REQUEST_SIZE_MATCH(xDPMSDisableReq);
372 
373     return ProcDPMSDisable(client);
374 }
375 
376 static int _X_COLD
SProcDPMSForceLevel(ClientPtr client)377 SProcDPMSForceLevel(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 
389 static int _X_COLD
SProcDPMSInfo(ClientPtr client)390 SProcDPMSInfo(ClientPtr client)
391 {
392     REQUEST(xDPMSInfoReq);
393 
394     swaps(&stuff->length);
395     REQUEST_SIZE_MATCH(xDPMSInfoReq);
396 
397     return ProcDPMSInfo(client);
398 }
399 
400 static int _X_COLD
SProcDPMSDispatch(ClientPtr client)401 SProcDPMSDispatch(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 
426 static void
DPMSCloseDownExtension(ExtensionEntry * e)427 DPMSCloseDownExtension(ExtensionEntry *e)
428 {
429     DPMSSet(serverClient, DPMSModeOn);
430 }
431 
432 void
DPMSExtensionInit(void)433 DPMSExtensionInit(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