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