1 /*
2 * Copyright (c) 2008 NVIDIA, Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 /*
25 * Make sure that XTHREADS is defined, so that the
26 * LockDisplay/UnlockDisplay macros are expanded properly and the
27 * libXNVCtrl library properly protects the Display connection.
28 */
29
30 #define NEED_EVENTS
31 #define NEED_REPLIES
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <X11/Xlibint.h>
35 #include <X11/Xutil.h>
36 #include <X11/extensions/Xext.h>
37 #include <X11/extensions/extutil.h>
38
39 #if !defined(XTHREADS)
40 #define XTHREADS
41 #endif /* XTHREADS */
42
43 #include "NVCtrlLib.h"
44 #include "nv_control.h"
45
46 #define NVCTRL_EXT_EXISTS 1
47 #define NVCTRL_EXT_NEED_TARGET_SWAP 2
48 #define NVCTRL_EXT_64_BIT_ATTRIBUTES 4
49 #define NVCTRL_EXT_NEED_CHECK (1 << (sizeof(XPointer) - 1))
50
51 static XExtensionInfo _nvctrl_ext_info_data;
52 static XExtensionInfo *nvctrl_ext_info = &_nvctrl_ext_info_data;
53 static /* const */ char *nvctrl_extension_name = NV_CONTROL_NAME;
54
55 #define XNVCTRLCheckExtension(dpy,i,val) \
56 XextCheckExtension (dpy, i, nvctrl_extension_name, val)
57 #define XNVCTRLSimpleCheckExtension(dpy,i) \
58 XextSimpleCheckExtension (dpy, i, nvctrl_extension_name)
59
60 static int close_display();
61 static uintptr_t version_flags(Display *dpy, XExtDisplayInfo *info);
62 static Bool wire_to_event();
63 static /* const */ XExtensionHooks nvctrl_extension_hooks = {
64 NULL, /* create_gc */
65 NULL, /* copy_gc */
66 NULL, /* flush_gc */
67 NULL, /* free_gc */
68 NULL, /* create_font */
69 NULL, /* free_font */
70 close_display, /* close_display */
71 wire_to_event, /* wire_to_event */
72 NULL, /* event_to_wire */
73 NULL, /* error */
74 NULL, /* error_string */
75 };
76
77 static XEXT_GENERATE_FIND_DISPLAY (find_display, nvctrl_ext_info,
78 nvctrl_extension_name,
79 &nvctrl_extension_hooks,
80 NV_CONTROL_EVENTS,
81 (XPointer)NVCTRL_EXT_NEED_CHECK)
82
XEXT_GENERATE_CLOSE_DISPLAY(close_display,nvctrl_ext_info)83 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, nvctrl_ext_info)
84
85 /*
86 * NV-CONTROL versions 1.8 and 1.9 pack the target_type and target_id
87 * fields in reversed order. In order to talk to one of these servers,
88 * we need to swap these fields.
89 */
90
91 static void XNVCTRLCheckTargetData(Display *dpy, XExtDisplayInfo *info,
92 int *target_type, int *target_id)
93 {
94 uintptr_t flags = version_flags(dpy, info);
95
96 /* We need to swap the target_type and target_id */
97 if (flags & NVCTRL_EXT_NEED_TARGET_SWAP) {
98 int tmp;
99 tmp = *target_type;
100 *target_type = *target_id;
101 *target_id = tmp;
102 }
103 }
104
105
XNVCTRLQueryExtension(Display * dpy,int * event_basep,int * error_basep)106 Bool XNVCTRLQueryExtension (
107 Display *dpy,
108 int *event_basep,
109 int *error_basep
110 ){
111 XExtDisplayInfo *info = find_display (dpy);
112
113 if (XextHasExtension(info)) {
114 if (event_basep) *event_basep = info->codes->first_event;
115 if (error_basep) *error_basep = info->codes->first_error;
116 return True;
117 } else {
118 return False;
119 }
120 }
121
122 /*
123 * Retrieve any cached flags that depend on the version of the NV-CONTROL
124 * extension.
125 */
126
version_flags(Display * dpy,XExtDisplayInfo * info)127 static uintptr_t version_flags(Display *dpy, XExtDisplayInfo *info)
128 {
129 uintptr_t data = (uintptr_t)info->data;
130
131 /* If necessary, determine the NV-CONTROL version */
132 if (data & NVCTRL_EXT_NEED_CHECK) {
133 int major, minor;
134 data = 0;
135 if (XNVCTRLQueryVersion(dpy, &major, &minor)) {
136 data |= NVCTRL_EXT_EXISTS;
137 if (major == 1 && (minor == 8 || minor == 9)) {
138 data |= NVCTRL_EXT_NEED_TARGET_SWAP;
139 }
140 if ((major > 1) || ((major == 1) && (minor > 20))) {
141 data |= NVCTRL_EXT_64_BIT_ATTRIBUTES;
142 }
143 }
144
145 info->data = (XPointer)data;
146 }
147
148 return data;
149 }
150
XNVCTRLQueryVersion(Display * dpy,int * major,int * minor)151 Bool XNVCTRLQueryVersion (
152 Display *dpy,
153 int *major,
154 int *minor
155 ){
156 XExtDisplayInfo *info = find_display (dpy);
157 xnvCtrlQueryExtensionReply rep;
158 xnvCtrlQueryExtensionReq *req;
159
160 if(!XextHasExtension(info))
161 return False;
162
163 XNVCTRLCheckExtension (dpy, info, False);
164
165 LockDisplay (dpy);
166 GetReq (nvCtrlQueryExtension, req);
167 req->reqType = info->codes->major_opcode;
168 req->nvReqType = X_nvCtrlQueryExtension;
169 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
170 UnlockDisplay (dpy);
171 SyncHandle ();
172 return False;
173 }
174 if (major) *major = rep.major;
175 if (minor) *minor = rep.minor;
176 UnlockDisplay (dpy);
177 SyncHandle ();
178 return True;
179 }
180
181
XNVCTRLIsNvScreen(Display * dpy,int screen)182 Bool XNVCTRLIsNvScreen (
183 Display *dpy,
184 int screen
185 ){
186 XExtDisplayInfo *info = find_display (dpy);
187 xnvCtrlIsNvReply rep;
188 xnvCtrlIsNvReq *req;
189 Bool isnv;
190
191 if(!XextHasExtension(info))
192 return False;
193
194 XNVCTRLCheckExtension (dpy, info, False);
195
196 LockDisplay (dpy);
197 GetReq (nvCtrlIsNv, req);
198 req->reqType = info->codes->major_opcode;
199 req->nvReqType = X_nvCtrlIsNv;
200 req->screen = screen;
201 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
202 UnlockDisplay (dpy);
203 SyncHandle ();
204 return False;
205 }
206 isnv = rep.isnv;
207 UnlockDisplay (dpy);
208 SyncHandle ();
209 return isnv;
210 }
211
212
XNVCTRLQueryTargetCount(Display * dpy,int target_type,int * value)213 Bool XNVCTRLQueryTargetCount (
214 Display *dpy,
215 int target_type,
216 int *value
217 ){
218 XExtDisplayInfo *info = find_display (dpy);
219 xnvCtrlQueryTargetCountReply rep;
220 xnvCtrlQueryTargetCountReq *req;
221
222 if(!XextHasExtension(info))
223 return False;
224
225 XNVCTRLCheckExtension (dpy, info, False);
226
227 LockDisplay (dpy);
228 GetReq (nvCtrlQueryTargetCount, req);
229 req->reqType = info->codes->major_opcode;
230 req->nvReqType = X_nvCtrlQueryTargetCount;
231 req->target_type = target_type;
232 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
233 UnlockDisplay (dpy);
234 SyncHandle ();
235 return False;
236 }
237 if (value) *value = rep.count;
238 UnlockDisplay (dpy);
239 SyncHandle ();
240 return True;
241 }
242
243
XNVCTRLSetTargetAttribute(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,int value)244 void XNVCTRLSetTargetAttribute (
245 Display *dpy,
246 int target_type,
247 int target_id,
248 unsigned int display_mask,
249 unsigned int attribute,
250 int value
251 ){
252 XExtDisplayInfo *info = find_display (dpy);
253 xnvCtrlSetAttributeReq *req;
254
255 XNVCTRLSimpleCheckExtension (dpy, info);
256 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
257
258 LockDisplay (dpy);
259 GetReq (nvCtrlSetAttribute, req);
260 req->reqType = info->codes->major_opcode;
261 req->nvReqType = X_nvCtrlSetAttribute;
262 req->target_type = target_type;
263 req->target_id = target_id;
264 req->display_mask = display_mask;
265 req->attribute = attribute;
266 req->value = value;
267 UnlockDisplay (dpy);
268 SyncHandle ();
269 }
270
XNVCTRLSetAttribute(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,int value)271 void XNVCTRLSetAttribute (
272 Display *dpy,
273 int screen,
274 unsigned int display_mask,
275 unsigned int attribute,
276 int value
277 ){
278 XNVCTRLSetTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen,
279 display_mask, attribute, value);
280 }
281
282
XNVCTRLSetTargetAttributeAndGetStatus(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,int value)283 Bool XNVCTRLSetTargetAttributeAndGetStatus (
284 Display *dpy,
285 int target_type,
286 int target_id,
287 unsigned int display_mask,
288 unsigned int attribute,
289 int value
290 ){
291 XExtDisplayInfo *info = find_display (dpy);
292 xnvCtrlSetAttributeAndGetStatusReq *req;
293 xnvCtrlSetAttributeAndGetStatusReply rep;
294 Bool success;
295
296 if(!XextHasExtension(info))
297 return False;
298
299 XNVCTRLCheckExtension (dpy, info, False);
300
301 LockDisplay (dpy);
302 GetReq (nvCtrlSetAttributeAndGetStatus, req);
303 req->reqType = info->codes->major_opcode;
304 req->nvReqType = X_nvCtrlSetAttributeAndGetStatus;
305 req->target_type = target_type;
306 req->target_id = target_id;
307 req->display_mask = display_mask;
308 req->attribute = attribute;
309 req->value = value;
310 if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
311 UnlockDisplay (dpy);
312 SyncHandle ();
313 return False;
314 }
315 UnlockDisplay (dpy);
316 SyncHandle ();
317
318 success = rep.flags;
319 return success;
320 }
321
XNVCTRLSetAttributeAndGetStatus(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,int value)322 Bool XNVCTRLSetAttributeAndGetStatus (
323 Display *dpy,
324 int screen,
325 unsigned int display_mask,
326 unsigned int attribute,
327 int value
328 ){
329 return XNVCTRLSetTargetAttributeAndGetStatus(dpy,
330 NV_CTRL_TARGET_TYPE_X_SCREEN,
331 screen, display_mask,
332 attribute, value);
333 }
334
335
XNVCTRLQueryTargetAttribute(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,int * value)336 Bool XNVCTRLQueryTargetAttribute (
337 Display *dpy,
338 int target_type,
339 int target_id,
340 unsigned int display_mask,
341 unsigned int attribute,
342 int *value
343 ){
344 XExtDisplayInfo *info = find_display (dpy);
345 xnvCtrlQueryAttributeReply rep;
346 xnvCtrlQueryAttributeReq *req;
347 Bool exists;
348
349 if(!XextHasExtension(info))
350 return False;
351
352 XNVCTRLCheckExtension (dpy, info, False);
353 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
354
355 LockDisplay (dpy);
356 GetReq (nvCtrlQueryAttribute, req);
357 req->reqType = info->codes->major_opcode;
358 req->nvReqType = X_nvCtrlQueryAttribute;
359 req->target_type = target_type;
360 req->target_id = target_id;
361 req->display_mask = display_mask;
362 req->attribute = attribute;
363 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
364 UnlockDisplay (dpy);
365 SyncHandle ();
366 return False;
367 }
368 exists = rep.flags;
369 if (exists && value) *value = rep.value;
370 UnlockDisplay (dpy);
371 SyncHandle ();
372 return exists;
373 }
374
XNVCTRLQueryAttribute(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,int * value)375 Bool XNVCTRLQueryAttribute (
376 Display *dpy,
377 int screen,
378 unsigned int display_mask,
379 unsigned int attribute,
380 int *value
381 ){
382 return XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
383 screen, display_mask, attribute, value);
384 }
385
386
XNVCTRLQueryTargetAttribute64(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,int64_t * value)387 Bool XNVCTRLQueryTargetAttribute64 (
388 Display *dpy,
389 int target_type,
390 int target_id,
391 unsigned int display_mask,
392 unsigned int attribute,
393 int64_t *value
394 ){
395 XExtDisplayInfo *info = find_display(dpy);
396 xnvCtrlQueryAttribute64Reply rep;
397 xnvCtrlQueryAttributeReq *req;
398 Bool exists;
399
400 if (!XextHasExtension(info))
401 return False;
402
403 XNVCTRLCheckExtension(dpy, info, False);
404 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
405
406 LockDisplay(dpy);
407 GetReq(nvCtrlQueryAttribute, req);
408 req->reqType = info->codes->major_opcode;
409 req->nvReqType = X_nvCtrlQueryAttribute64;
410 req->target_type = target_type;
411 req->target_id = target_id;
412 req->display_mask = display_mask;
413 req->attribute = attribute;
414 if (!_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
415 UnlockDisplay(dpy);
416 SyncHandle();
417 return False;
418 }
419 exists = rep.flags;
420 if (exists && value) *value = rep.value_64;
421 UnlockDisplay(dpy);
422 SyncHandle();
423 return exists;
424 }
425
426
XNVCTRLQueryTargetStringAttribute(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,char ** ptr)427 Bool XNVCTRLQueryTargetStringAttribute (
428 Display *dpy,
429 int target_type,
430 int target_id,
431 unsigned int display_mask,
432 unsigned int attribute,
433 char **ptr
434 ){
435 XExtDisplayInfo *info = find_display (dpy);
436 xnvCtrlQueryStringAttributeReply rep;
437 xnvCtrlQueryStringAttributeReq *req;
438 Bool exists;
439 int length, numbytes, slop;
440
441 if (!ptr) return False;
442
443 if(!XextHasExtension(info))
444 return False;
445
446 XNVCTRLCheckExtension (dpy, info, False);
447 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
448
449 LockDisplay (dpy);
450 GetReq (nvCtrlQueryStringAttribute, req);
451 req->reqType = info->codes->major_opcode;
452 req->nvReqType = X_nvCtrlQueryStringAttribute;
453 req->target_type = target_type;
454 req->target_id = target_id;
455 req->display_mask = display_mask;
456 req->attribute = attribute;
457 if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
458 UnlockDisplay (dpy);
459 SyncHandle ();
460 return False;
461 }
462 length = rep.length;
463 numbytes = rep.n;
464 slop = numbytes & 3;
465 exists = rep.flags;
466 if (exists) {
467 *ptr = (char *) Xmalloc(numbytes);
468 }
469 if (!exists || !*ptr) {
470 _XEatData(dpy, length);
471 UnlockDisplay (dpy);
472 SyncHandle ();
473 return False;
474 } else {
475 _XRead(dpy, (char *) *ptr, numbytes);
476 if (slop) _XEatData(dpy, 4-slop);
477 }
478 UnlockDisplay (dpy);
479 SyncHandle ();
480 return exists;
481 }
482
XNVCTRLQueryStringAttribute(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,char ** ptr)483 Bool XNVCTRLQueryStringAttribute (
484 Display *dpy,
485 int screen,
486 unsigned int display_mask,
487 unsigned int attribute,
488 char **ptr
489 ){
490 return XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
491 screen, display_mask,
492 attribute, ptr);
493 }
494
495
XNVCTRLSetTargetStringAttribute(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,char * ptr)496 Bool XNVCTRLSetTargetStringAttribute (
497 Display *dpy,
498 int target_type,
499 int target_id,
500 unsigned int display_mask,
501 unsigned int attribute,
502 char *ptr
503 ){
504 XExtDisplayInfo *info = find_display (dpy);
505 xnvCtrlSetStringAttributeReq *req;
506 xnvCtrlSetStringAttributeReply rep;
507 int size;
508 Bool success;
509
510 if(!XextHasExtension(info))
511 return False;
512
513 XNVCTRLCheckExtension (dpy, info, False);
514
515 size = strlen(ptr)+1;
516
517 LockDisplay (dpy);
518 GetReq (nvCtrlSetStringAttribute, req);
519 req->reqType = info->codes->major_opcode;
520 req->nvReqType = X_nvCtrlSetStringAttribute;
521 req->target_type = target_type;
522 req->target_id = target_id;
523 req->display_mask = display_mask;
524 req->attribute = attribute;
525 req->length += ((size + 3) & ~3) >> 2;
526 req->num_bytes = size;
527 Data(dpy, ptr, size);
528
529 if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
530 UnlockDisplay (dpy);
531 SyncHandle ();
532 return False;
533 }
534 UnlockDisplay (dpy);
535 SyncHandle ();
536
537 success = rep.flags;
538 return success;
539 }
540
XNVCTRLSetStringAttribute(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,char * ptr)541 Bool XNVCTRLSetStringAttribute (
542 Display *dpy,
543 int screen,
544 unsigned int display_mask,
545 unsigned int attribute,
546 char *ptr
547 ){
548 return XNVCTRLSetTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
549 screen, display_mask,
550 attribute, ptr);
551 }
552
553
XNVCTRLQueryValidTargetAttributeValues32(Display * dpy,XExtDisplayInfo * info,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,NVCTRLAttributeValidValuesRec * values)554 static Bool XNVCTRLQueryValidTargetAttributeValues32 (
555 Display *dpy,
556 XExtDisplayInfo *info,
557 int target_type,
558 int target_id,
559 unsigned int display_mask,
560 unsigned int attribute,
561 NVCTRLAttributeValidValuesRec *values
562 ){
563 xnvCtrlQueryValidAttributeValuesReply rep;
564 xnvCtrlQueryValidAttributeValuesReq *req;
565 Bool exists;
566
567 LockDisplay (dpy);
568 GetReq (nvCtrlQueryValidAttributeValues, req);
569 req->reqType = info->codes->major_opcode;
570 req->nvReqType = X_nvCtrlQueryValidAttributeValues;
571 req->target_type = target_type;
572 req->target_id = target_id;
573 req->display_mask = display_mask;
574 req->attribute = attribute;
575 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
576 UnlockDisplay (dpy);
577 SyncHandle ();
578 return False;
579 }
580 exists = rep.flags;
581 if (exists) {
582 values->type = rep.attr_type;
583 if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) {
584 values->u.range.min = rep.min;
585 values->u.range.max = rep.max;
586 }
587 if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) {
588 values->u.bits.ints = rep.bits;
589 }
590 values->permissions = rep.perms;
591 }
592 UnlockDisplay (dpy);
593 SyncHandle ();
594 return exists;
595 }
596
597
XNVCTRLQueryValidTargetStringAttributeValues(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,NVCTRLAttributeValidValuesRec * values)598 Bool XNVCTRLQueryValidTargetStringAttributeValues (
599 Display *dpy,
600 int target_type,
601 int target_id,
602 unsigned int display_mask,
603 unsigned int attribute,
604 NVCTRLAttributeValidValuesRec *values
605 ){
606 XExtDisplayInfo *info = find_display(dpy);
607 Bool exists;
608 xnvCtrlQueryValidAttributeValuesReply rep;
609 xnvCtrlQueryValidAttributeValuesReq *req;
610
611 if (!values) return False;
612
613 if (!XextHasExtension(info))
614 return False;
615
616 XNVCTRLCheckExtension(dpy, info, False);
617
618 LockDisplay(dpy);
619 GetReq (nvCtrlQueryValidAttributeValues, req);
620 req->reqType = info->codes->major_opcode;
621 req->nvReqType = X_nvCtrlQueryValidStringAttributeValues;
622 req->target_type = target_type;
623 req->target_id = target_id;
624 req->display_mask = display_mask;
625 req->attribute = attribute;
626 if (!_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
627 UnlockDisplay(dpy);
628 SyncHandle();
629 return False;
630 }
631 exists = rep.flags;
632 if (exists) {
633 values->type = rep.attr_type;
634 values->permissions = rep.perms;
635 }
636 UnlockDisplay(dpy);
637 SyncHandle();
638 return exists;
639 }
640
641
XNVCTRLQueryValidTargetAttributeValues64(Display * dpy,XExtDisplayInfo * info,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,NVCTRLAttributeValidValuesRec * values)642 static Bool XNVCTRLQueryValidTargetAttributeValues64 (
643 Display *dpy,
644 XExtDisplayInfo *info,
645 int target_type,
646 int target_id,
647 unsigned int display_mask,
648 unsigned int attribute,
649 NVCTRLAttributeValidValuesRec *values
650 ){
651 xnvCtrlQueryValidAttributeValues64Reply rep;
652 xnvCtrlQueryValidAttributeValuesReq *req;
653 Bool exists;
654
655 LockDisplay(dpy);
656 GetReq(nvCtrlQueryValidAttributeValues, req);
657 req->reqType = info->codes->major_opcode;
658 req->nvReqType = X_nvCtrlQueryValidAttributeValues64;
659 req->target_type = target_type;
660 req->target_id = target_id;
661 req->display_mask = display_mask;
662 req->attribute = attribute;
663 if (!_XReply(dpy, (xReply *)&rep,
664 sz_xnvCtrlQueryValidAttributeValues64Reply_extra,
665 xTrue)) {
666 UnlockDisplay(dpy);
667 SyncHandle();
668 return False;
669 }
670 exists = rep.flags;
671 if (exists) {
672 values->type = rep.attr_type;
673 if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) {
674 values->u.range.min = rep.min_64;
675 values->u.range.max = rep.max_64;
676 }
677 if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) {
678 values->u.bits.ints = rep.bits_64;
679 }
680 values->permissions = rep.perms;
681 }
682 UnlockDisplay(dpy);
683 SyncHandle();
684 return exists;
685 }
686
XNVCTRLQueryValidTargetAttributeValues(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,NVCTRLAttributeValidValuesRec * values)687 Bool XNVCTRLQueryValidTargetAttributeValues (
688 Display *dpy,
689 int target_type,
690 int target_id,
691 unsigned int display_mask,
692 unsigned int attribute,
693 NVCTRLAttributeValidValuesRec *values
694 ){
695 XExtDisplayInfo *info = find_display(dpy);
696 Bool exists;
697 uintptr_t flags;
698
699 if (!values) return False;
700
701 if (!XextHasExtension(info))
702 return False;
703
704 XNVCTRLCheckExtension(dpy, info, False);
705 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
706
707 flags = version_flags(dpy,info);
708
709 if (!(flags & NVCTRL_EXT_EXISTS))
710 return False;
711
712 if (flags & NVCTRL_EXT_64_BIT_ATTRIBUTES) {
713 exists = XNVCTRLQueryValidTargetAttributeValues64(dpy, info,
714 target_type,
715 target_id,
716 display_mask,
717 attribute,
718 values);
719 } else {
720 exists = XNVCTRLQueryValidTargetAttributeValues32(dpy, info,
721 target_type,
722 target_id,
723 display_mask,
724 attribute,
725 values);
726 }
727 return exists;
728 }
729
730
XNVCTRLQueryValidAttributeValues(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,NVCTRLAttributeValidValuesRec * values)731 Bool XNVCTRLQueryValidAttributeValues (
732 Display *dpy,
733 int screen,
734 unsigned int display_mask,
735 unsigned int attribute,
736 NVCTRLAttributeValidValuesRec *values
737 ){
738 return XNVCTRLQueryValidTargetAttributeValues(dpy,
739 NV_CTRL_TARGET_TYPE_X_SCREEN,
740 screen, display_mask,
741 attribute, values);
742 }
743
744
QueryAttributePermissionsInternal(Display * dpy,unsigned int attribute,NVCTRLAttributePermissionsRec * permissions,unsigned int reqType)745 static Bool QueryAttributePermissionsInternal (
746 Display *dpy,
747 unsigned int attribute,
748 NVCTRLAttributePermissionsRec *permissions,
749 unsigned int reqType
750 ){
751 XExtDisplayInfo *info = find_display (dpy);
752 xnvCtrlQueryAttributePermissionsReply rep;
753 xnvCtrlQueryAttributePermissionsReq *req;
754 Bool exists;
755
756 if(!XextHasExtension(info))
757 return False;
758
759 XNVCTRLCheckExtension (dpy, info, False);
760
761 LockDisplay(dpy);
762 GetReq(nvCtrlQueryAttributePermissions, req);
763 req->reqType = info->codes->major_opcode;
764 req->nvReqType = reqType;
765 req->attribute = attribute;
766 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
767 UnlockDisplay (dpy);
768 SyncHandle();
769 return False;
770 }
771 exists = rep.flags;
772 if (exists && permissions) {
773 permissions->type = rep.attr_type;
774 permissions->permissions = rep.perms;
775 }
776 UnlockDisplay(dpy);
777 SyncHandle();
778 return exists;
779 }
780
781
XNVCTRLQueryAttributePermissions(Display * dpy,unsigned int attribute,NVCTRLAttributePermissionsRec * permissions)782 Bool XNVCTRLQueryAttributePermissions (
783 Display *dpy,
784 unsigned int attribute,
785 NVCTRLAttributePermissionsRec *permissions
786 ){
787 return QueryAttributePermissionsInternal(dpy,
788 attribute,
789 permissions,
790 X_nvCtrlQueryAttributePermissions);
791 }
792
793
XNVCTRLQueryStringAttributePermissions(Display * dpy,unsigned int attribute,NVCTRLAttributePermissionsRec * permissions)794 Bool XNVCTRLQueryStringAttributePermissions (
795 Display *dpy,
796 unsigned int attribute,
797 NVCTRLAttributePermissionsRec *permissions
798 ){
799 return QueryAttributePermissionsInternal(dpy,
800 attribute,
801 permissions,
802 X_nvCtrlQueryStringAttributePermissions);
803 }
804
805
XNVCTRLQueryBinaryDataAttributePermissions(Display * dpy,unsigned int attribute,NVCTRLAttributePermissionsRec * permissions)806 Bool XNVCTRLQueryBinaryDataAttributePermissions (
807 Display *dpy,
808 unsigned int attribute,
809 NVCTRLAttributePermissionsRec *permissions
810 ){
811 return QueryAttributePermissionsInternal(dpy,
812 attribute,
813 permissions,
814 X_nvCtrlQueryBinaryDataAttributePermissions);
815 }
816
817
XNVCTRLQueryStringOperationAttributePermissions(Display * dpy,unsigned int attribute,NVCTRLAttributePermissionsRec * permissions)818 Bool XNVCTRLQueryStringOperationAttributePermissions (
819 Display *dpy,
820 unsigned int attribute,
821 NVCTRLAttributePermissionsRec *permissions
822 ){
823 return QueryAttributePermissionsInternal(dpy,
824 attribute,
825 permissions,
826 X_nvCtrlQueryStringOperationAttributePermissions);
827 }
828
829
XNVCTRLSetGvoColorConversion(Display * dpy,int screen,float colorMatrix[3][3],float colorOffset[3],float colorScale[3])830 void XNVCTRLSetGvoColorConversion (
831 Display *dpy,
832 int screen,
833 float colorMatrix[3][3],
834 float colorOffset[3],
835 float colorScale[3]
836 ){
837 XExtDisplayInfo *info = find_display (dpy);
838 xnvCtrlSetGvoColorConversionReq *req;
839
840 XNVCTRLSimpleCheckExtension (dpy, info);
841
842 LockDisplay (dpy);
843 GetReq (nvCtrlSetGvoColorConversion, req);
844 req->reqType = info->codes->major_opcode;
845 req->nvReqType = X_nvCtrlSetGvoColorConversion;
846 req->screen = screen;
847
848 req->cscMatrix_y_r = colorMatrix[0][0];
849 req->cscMatrix_y_g = colorMatrix[0][1];
850 req->cscMatrix_y_b = colorMatrix[0][2];
851
852 req->cscMatrix_cr_r = colorMatrix[1][0];
853 req->cscMatrix_cr_g = colorMatrix[1][1];
854 req->cscMatrix_cr_b = colorMatrix[1][2];
855
856 req->cscMatrix_cb_r = colorMatrix[2][0];
857 req->cscMatrix_cb_g = colorMatrix[2][1];
858 req->cscMatrix_cb_b = colorMatrix[2][2];
859
860 req->cscOffset_y = colorOffset[0];
861 req->cscOffset_cr = colorOffset[1];
862 req->cscOffset_cb = colorOffset[2];
863
864 req->cscScale_y = colorScale[0];
865 req->cscScale_cr = colorScale[1];
866 req->cscScale_cb = colorScale[2];
867
868 UnlockDisplay (dpy);
869 SyncHandle ();
870 }
871
872
XNVCTRLQueryGvoColorConversion(Display * dpy,int screen,float colorMatrix[3][3],float colorOffset[3],float colorScale[3])873 Bool XNVCTRLQueryGvoColorConversion (
874 Display *dpy,
875 int screen,
876 float colorMatrix[3][3],
877 float colorOffset[3],
878 float colorScale[3]
879 ){
880 XExtDisplayInfo *info = find_display (dpy);
881 xnvCtrlQueryGvoColorConversionReply rep;
882 xnvCtrlQueryGvoColorConversionReq *req;
883
884 if(!XextHasExtension(info))
885 return False;
886
887 XNVCTRLCheckExtension (dpy, info, False);
888
889 LockDisplay (dpy);
890
891 GetReq (nvCtrlQueryGvoColorConversion, req);
892 req->reqType = info->codes->major_opcode;
893 req->nvReqType = X_nvCtrlQueryGvoColorConversion;
894 req->screen = screen;
895
896 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
897 UnlockDisplay (dpy);
898 SyncHandle ();
899 return False;
900 }
901
902 _XRead(dpy, (char *)(colorMatrix), 36);
903 _XRead(dpy, (char *)(colorOffset), 12);
904 _XRead(dpy, (char *)(colorScale), 12);
905
906 UnlockDisplay (dpy);
907 SyncHandle ();
908
909 return True;
910 }
911
912
XNVCtrlSelectTargetNotify(Display * dpy,int target_type,int target_id,int notify_type,Bool onoff)913 Bool XNVCtrlSelectTargetNotify (
914 Display *dpy,
915 int target_type,
916 int target_id,
917 int notify_type,
918 Bool onoff
919 ){
920 XExtDisplayInfo *info = find_display (dpy);
921 xnvCtrlSelectTargetNotifyReq *req;
922
923 if(!XextHasExtension (info))
924 return False;
925
926 XNVCTRLCheckExtension (dpy, info, False);
927
928 LockDisplay (dpy);
929 GetReq (nvCtrlSelectTargetNotify, req);
930 req->reqType = info->codes->major_opcode;
931 req->nvReqType = X_nvCtrlSelectTargetNotify;
932 req->target_type = target_type;
933 req->target_id = target_id;
934 req->notifyType = notify_type;
935 req->onoff = onoff;
936 UnlockDisplay (dpy);
937 SyncHandle ();
938
939 return True;
940 }
941
942
XNVCtrlSelectNotify(Display * dpy,int screen,int type,Bool onoff)943 Bool XNVCtrlSelectNotify (
944 Display *dpy,
945 int screen,
946 int type,
947 Bool onoff
948 ){
949 XExtDisplayInfo *info = find_display (dpy);
950 xnvCtrlSelectNotifyReq *req;
951
952 if(!XextHasExtension (info))
953 return False;
954
955 XNVCTRLCheckExtension (dpy, info, False);
956
957 LockDisplay (dpy);
958 GetReq (nvCtrlSelectNotify, req);
959 req->reqType = info->codes->major_opcode;
960 req->nvReqType = X_nvCtrlSelectNotify;
961 req->screen = screen;
962 req->notifyType = type;
963 req->onoff = onoff;
964 UnlockDisplay (dpy);
965 SyncHandle ();
966
967 return True;
968 }
969
XNVCTRLQueryTargetBinaryData(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,unsigned char ** ptr,int * len)970 Bool XNVCTRLQueryTargetBinaryData (
971 Display *dpy,
972 int target_type,
973 int target_id,
974 unsigned int display_mask,
975 unsigned int attribute,
976 unsigned char **ptr,
977 int *len
978 ){
979 XExtDisplayInfo *info = find_display (dpy);
980 xnvCtrlQueryBinaryDataReply rep;
981 xnvCtrlQueryBinaryDataReq *req;
982 Bool exists;
983 int length, numbytes, slop;
984
985 if (!ptr) return False;
986
987 if(!XextHasExtension(info))
988 return False;
989
990 XNVCTRLCheckExtension (dpy, info, False);
991 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
992
993 LockDisplay (dpy);
994 GetReq (nvCtrlQueryBinaryData, req);
995 req->reqType = info->codes->major_opcode;
996 req->nvReqType = X_nvCtrlQueryBinaryData;
997 req->target_type = target_type;
998 req->target_id = target_id;
999 req->display_mask = display_mask;
1000 req->attribute = attribute;
1001 if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
1002 UnlockDisplay (dpy);
1003 SyncHandle ();
1004 return False;
1005 }
1006 length = rep.length;
1007 numbytes = rep.n;
1008 slop = numbytes & 3;
1009 exists = rep.flags;
1010 if (exists) {
1011 *ptr = (unsigned char *) Xmalloc(numbytes);
1012 }
1013 if (!exists || !*ptr) {
1014 _XEatData(dpy, length);
1015 UnlockDisplay (dpy);
1016 SyncHandle ();
1017 return False;
1018 } else {
1019 _XRead(dpy, (char *) *ptr, numbytes);
1020 if (slop) _XEatData(dpy, 4-slop);
1021 }
1022 if (len) *len = numbytes;
1023 UnlockDisplay (dpy);
1024 SyncHandle ();
1025 return exists;
1026 }
1027
XNVCTRLQueryBinaryData(Display * dpy,int screen,unsigned int display_mask,unsigned int attribute,unsigned char ** ptr,int * len)1028 Bool XNVCTRLQueryBinaryData (
1029 Display *dpy,
1030 int screen,
1031 unsigned int display_mask,
1032 unsigned int attribute,
1033 unsigned char **ptr,
1034 int *len
1035 ){
1036 return XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
1037 screen, display_mask,
1038 attribute, ptr, len);
1039 }
1040
XNVCTRLStringOperation(Display * dpy,int target_type,int target_id,unsigned int display_mask,unsigned int attribute,char * pIn,char ** ppOut)1041 Bool XNVCTRLStringOperation (
1042 Display *dpy,
1043 int target_type,
1044 int target_id,
1045 unsigned int display_mask,
1046 unsigned int attribute,
1047 char *pIn,
1048 char **ppOut
1049 ) {
1050 XExtDisplayInfo *info = find_display(dpy);
1051 xnvCtrlStringOperationReq *req;
1052 xnvCtrlStringOperationReply rep;
1053 Bool ret;
1054 int inSize, outSize, length, slop;
1055
1056 if (!XextHasExtension(info))
1057 return False;
1058
1059 if (!ppOut)
1060 return False;
1061
1062 *ppOut = NULL;
1063
1064 XNVCTRLCheckExtension(dpy, info, False);
1065 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
1066
1067 if (pIn) {
1068 inSize = strlen(pIn) + 1;
1069 } else {
1070 inSize = 0;
1071 }
1072
1073 LockDisplay(dpy);
1074 GetReq(nvCtrlStringOperation, req);
1075
1076 req->reqType = info->codes->major_opcode;
1077 req->nvReqType = X_nvCtrlStringOperation;
1078 req->target_type = target_type;
1079 req->target_id = target_id;
1080 req->display_mask = display_mask;
1081 req->attribute = attribute;
1082
1083 req->length += ((inSize + 3) & ~3) >> 2;
1084 req->num_bytes = inSize;
1085
1086 if (pIn) {
1087 Data(dpy, pIn, inSize);
1088 }
1089
1090 if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
1091 UnlockDisplay(dpy);
1092 SyncHandle();
1093 return False;
1094 }
1095
1096 length = rep.length;
1097 outSize = rep.num_bytes;
1098 slop = outSize & 3;
1099
1100 if (outSize) *ppOut = (char *) Xmalloc(outSize);
1101
1102 if (!*ppOut) {
1103 _XEatData(dpy, length);
1104 } else {
1105 _XRead(dpy, (char *) *ppOut, outSize);
1106 if (slop) _XEatData(dpy, 4-slop);
1107 }
1108
1109 ret = rep.ret;
1110
1111 UnlockDisplay(dpy);
1112 SyncHandle();
1113
1114 return ret;
1115 }
1116
1117
wire_to_event(Display * dpy,XEvent * host,xEvent * wire)1118 static Bool wire_to_event (Display *dpy, XEvent *host, xEvent *wire)
1119 {
1120 XExtDisplayInfo *info = find_display (dpy);
1121 XNVCtrlEvent *re;
1122 xnvctrlEvent *event;
1123 XNVCtrlEventTarget *reTarget;
1124 xnvctrlEventTarget *eventTarget;
1125 XNVCtrlEventTargetAvailability *reTargetAvailability;
1126 XNVCtrlStringEventTarget *reTargetString;
1127 XNVCtrlBinaryEventTarget *reTargetBinary;
1128
1129 XNVCTRLCheckExtension (dpy, info, False);
1130
1131 switch ((wire->u.u.type & 0x7F) - info->codes->first_event) {
1132 case ATTRIBUTE_CHANGED_EVENT:
1133 re = (XNVCtrlEvent *) host;
1134 event = (xnvctrlEvent *) wire;
1135 re->attribute_changed.type = event->u.u.type & 0x7F;
1136 re->attribute_changed.serial =
1137 _XSetLastRequestRead(dpy, (xGenericReply*) event);
1138 re->attribute_changed.send_event = ((event->u.u.type & 0x80) != 0);
1139 re->attribute_changed.display = dpy;
1140 re->attribute_changed.time = event->u.attribute_changed.time;
1141 re->attribute_changed.screen = event->u.attribute_changed.screen;
1142 re->attribute_changed.display_mask =
1143 event->u.attribute_changed.display_mask;
1144 re->attribute_changed.attribute = event->u.attribute_changed.attribute;
1145 re->attribute_changed.value = event->u.attribute_changed.value;
1146 break;
1147 case TARGET_ATTRIBUTE_CHANGED_EVENT:
1148 reTarget = (XNVCtrlEventTarget *) host;
1149 eventTarget = (xnvctrlEventTarget *) wire;
1150 reTarget->attribute_changed.type = eventTarget->u.u.type & 0x7F;
1151 reTarget->attribute_changed.serial =
1152 _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
1153 reTarget->attribute_changed.send_event =
1154 ((eventTarget->u.u.type & 0x80) != 0);
1155 reTarget->attribute_changed.display = dpy;
1156 reTarget->attribute_changed.time =
1157 eventTarget->u.attribute_changed.time;
1158 reTarget->attribute_changed.target_type =
1159 eventTarget->u.attribute_changed.target_type;
1160 reTarget->attribute_changed.target_id =
1161 eventTarget->u.attribute_changed.target_id;
1162 reTarget->attribute_changed.display_mask =
1163 eventTarget->u.attribute_changed.display_mask;
1164 reTarget->attribute_changed.attribute =
1165 eventTarget->u.attribute_changed.attribute;
1166 reTarget->attribute_changed.value =
1167 eventTarget->u.attribute_changed.value;
1168 break;
1169 case TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT:
1170 reTargetAvailability = (XNVCtrlEventTargetAvailability *) host;
1171 eventTarget = (xnvctrlEventTarget *) wire;
1172 reTargetAvailability->attribute_changed.type =
1173 eventTarget->u.u.type & 0x7F;
1174 reTargetAvailability->attribute_changed.serial =
1175 _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
1176 reTargetAvailability->attribute_changed.send_event =
1177 ((eventTarget->u.u.type & 0x80) != 0);
1178 reTargetAvailability->attribute_changed.display = dpy;
1179 reTargetAvailability->attribute_changed.time =
1180 eventTarget->u.availability_changed.time;
1181 reTargetAvailability->attribute_changed.target_type =
1182 eventTarget->u.availability_changed.target_type;
1183 reTargetAvailability->attribute_changed.target_id =
1184 eventTarget->u.availability_changed.target_id;
1185 reTargetAvailability->attribute_changed.display_mask =
1186 eventTarget->u.availability_changed.display_mask;
1187 reTargetAvailability->attribute_changed.attribute =
1188 eventTarget->u.availability_changed.attribute;
1189 reTargetAvailability->attribute_changed.availability =
1190 eventTarget->u.availability_changed.availability;
1191 reTargetAvailability->attribute_changed.value =
1192 eventTarget->u.availability_changed.value;
1193 break;
1194 case TARGET_STRING_ATTRIBUTE_CHANGED_EVENT:
1195 reTargetString = (XNVCtrlStringEventTarget *) host;
1196 eventTarget = (xnvctrlEventTarget *) wire;
1197 reTargetString->attribute_changed.type = eventTarget->u.u.type & 0x7F;
1198 reTargetString->attribute_changed.serial =
1199 _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
1200 reTargetString->attribute_changed.send_event =
1201 ((eventTarget->u.u.type & 0x80) != 0);
1202 reTargetString->attribute_changed.display = dpy;
1203 reTargetString->attribute_changed.time =
1204 eventTarget->u.attribute_changed.time;
1205 reTargetString->attribute_changed.target_type =
1206 eventTarget->u.attribute_changed.target_type;
1207 reTargetString->attribute_changed.target_id =
1208 eventTarget->u.attribute_changed.target_id;
1209 reTargetString->attribute_changed.display_mask =
1210 eventTarget->u.attribute_changed.display_mask;
1211 reTargetString->attribute_changed.attribute =
1212 eventTarget->u.attribute_changed.attribute;
1213 break;
1214 case TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT:
1215 reTargetBinary = (XNVCtrlBinaryEventTarget *) host;
1216 eventTarget = (xnvctrlEventTarget *) wire;
1217 reTargetBinary->attribute_changed.type = eventTarget->u.u.type & 0x7F;
1218 reTargetBinary->attribute_changed.serial =
1219 _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
1220 reTargetBinary->attribute_changed.send_event =
1221 ((eventTarget->u.u.type & 0x80) != 0);
1222 reTargetBinary->attribute_changed.display = dpy;
1223 reTargetBinary->attribute_changed.time =
1224 eventTarget->u.attribute_changed.time;
1225 reTargetBinary->attribute_changed.target_type =
1226 eventTarget->u.attribute_changed.target_type;
1227 reTargetBinary->attribute_changed.target_id =
1228 eventTarget->u.attribute_changed.target_id;
1229 reTargetBinary->attribute_changed.display_mask =
1230 eventTarget->u.attribute_changed.display_mask;
1231 reTargetBinary->attribute_changed.attribute =
1232 eventTarget->u.attribute_changed.attribute;
1233 break;
1234
1235 default:
1236 return False;
1237 }
1238
1239 return True;
1240 }
1241
1242