~ubuntu-branches/ubuntu/precise/nvidia-settings/precise-proposed

« back to all changes in this revision

Viewing changes to nvidia-settings-1.0/src/query-assign.c

  • Committer: Bazaar Package Importer
  • Author(s): Randall Donald
  • Date: 2004-07-03 19:09:17 UTC
  • Revision ID: james.westby@ubuntu.com-20040703190917-rqkze2s58ux5pamy
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
 
3
 * and Linux systems.
 
4
 *
 
5
 * Copyright (C) 2004 NVIDIA Corporation.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of Version 2 of the GNU General Public
 
9
 * License as published by the Free Software Foundation.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
 
14
 * of the GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the:
 
18
 *
 
19
 *           Free Software Foundation, Inc.
 
20
 *           59 Temple Place - Suite 330
 
21
 *           Boston, MA 02111-1307, USA
 
22
 *
 
23
 */
 
24
 
 
25
/*
 
26
 * query-assign.c - this source file contains functions for querying
 
27
 * and assigning attributes, as specified on the command line.  Some
 
28
 * of this functionality is also shared with the config file
 
29
 * reader/writer.
 
30
 */
 
31
 
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
 
 
36
#include "parse.h"
 
37
#include "msg.h"
 
38
#include "query-assign.h"
 
39
 
 
40
/* local prototypes */
 
41
 
 
42
static int process_attribute_queries(int, char**, const char *);
 
43
 
 
44
static int process_attribute_assignments(int, char**, const char *);
 
45
 
 
46
static int query_all(const char *);
 
47
 
 
48
static void print_valid_values(char *, NVCTRLAttributeValidValuesRec);
 
49
 
 
50
static int validate_value(CtrlHandles *h, ParsedAttribute *a, uint32 d,
 
51
                          int screen, char *whence);
 
52
 
 
53
/*
 
54
 * nv_process_assignments_and_queries() - process any assignments or
 
55
 * queries specified on the commandline.  If an error occurs, return
 
56
 * NV_FALSE.  On success return NV_TRUE.
 
57
 */
 
58
 
 
59
int nv_process_assignments_and_queries(Options *op)
 
60
{
 
61
    int ret;
 
62
 
 
63
    if (op->num_queries) {
 
64
        ret = process_attribute_queries(op->num_queries,
 
65
                                        op->queries, op->ctrl_display);
 
66
        if (!ret) return NV_FALSE;
 
67
    }
 
68
 
 
69
    if (op->num_assignments) {
 
70
        ret = process_attribute_assignments(op->num_assignments,
 
71
                                            op->assignments,
 
72
                                            op->ctrl_display);
 
73
        if (!ret) return NV_FALSE;
 
74
    }
 
75
    
 
76
    return NV_TRUE;
 
77
 
 
78
} /* nv_process_assignments_and_queries() */
 
79
 
 
80
 
 
81
 
 
82
/*
 
83
 * nv_get_enabled_display_devices() - allocate an array of unsigned
 
84
 * ints of length n, and query the X server for each screen's enabled
 
85
 * display device mask, saving each X screen's display mask into the
 
86
 * appropriate index in the array.
 
87
 *
 
88
 * This is just an optimization to avoid redundant round trips to the
 
89
 * X server later in NvCtrlProcessParsedAttribute().
 
90
 *
 
91
 * On success a freshly malloc'ed array of length n is returned (it is
 
92
 * the caller's responsibility to free this memory).  On error an
 
93
 * error message is printed and NULL is returned.
 
94
 */
 
95
 
 
96
uint32 *nv_get_enabled_display_devices(int n, NvCtrlAttributeHandle **h)
 
97
{
 
98
    ReturnStatus status;
 
99
    uint32 *d;
 
100
    int screen;
 
101
    
 
102
    d = malloc(sizeof(uint32) * n);
 
103
    
 
104
    for (screen = 0; screen < n; screen++) {
 
105
        if (!h[screen]) {
 
106
            d[screen] = 0x0;
 
107
            continue;
 
108
        }
 
109
 
 
110
        status = NvCtrlGetAttribute(h[screen], NV_CTRL_ENABLED_DISPLAYS,
 
111
                                    &d[screen]);
 
112
        if (status != NvCtrlSuccess) {
 
113
            nv_error_msg("Error querying enabled displays on "
 
114
                         "screen %d (%s).", screen,
 
115
                         NvCtrlAttributesStrError(status));
 
116
            free(d);
 
117
            return NULL;
 
118
        }
 
119
    }
 
120
 
 
121
    return d;
 
122
 
 
123
} /* nv_get_enabled_display_devices() */
 
124
 
 
125
 
 
126
 
 
127
/*
 
128
 * nv_alloc_ctrl_handles() - allocate a new CtrlHandles structure,
 
129
 * connect to the X server identified by display, and initialize an
 
130
 * NvCtrlAttributeHandle for each X screen.
 
131
 */
 
132
 
 
133
CtrlHandles *nv_alloc_ctrl_handles(const char *display)
 
134
{
 
135
    CtrlHandles *h;
 
136
    int i;
 
137
 
 
138
    h = malloc(sizeof(CtrlHandles));
 
139
 
 
140
    if (display) h->display = strdup(display);
 
141
    else h->display = NULL;
 
142
    
 
143
    h->dpy = XOpenDisplay(h->display);
 
144
 
 
145
    if (h->dpy) {
 
146
        
 
147
        h->num_screens = ScreenCount(h->dpy);
 
148
        
 
149
        h->h = malloc(h->num_screens * sizeof(NvCtrlAttributeHandle *));
 
150
        h->screen_names = malloc(h->num_screens * sizeof(char *));
 
151
 
 
152
        for (i = 0; i < h->num_screens; i++) {
 
153
            h->h[i] = NvCtrlAttributeInit
 
154
                (h->dpy, i, NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS);
 
155
            h->screen_names[i] = NvCtrlGetDisplayName(h->h[i]);
 
156
        }
 
157
            
 
158
        h->d = nv_get_enabled_display_devices(h->num_screens, h->h);
 
159
        
 
160
    } else {
 
161
 
 
162
        nv_error_msg("Cannot open display '%s'.", XDisplayName(h->display));
 
163
        
 
164
        h->num_screens = 0;
 
165
        h->h = NULL;
 
166
        h->d = NULL;
 
167
        h->screen_names = NULL;
 
168
    }
 
169
 
 
170
    return h;
 
171
 
 
172
} /* nv_alloc_ctrl_handles() */
 
173
 
 
174
 
 
175
/*
 
176
 * nv_free_ctrl_handles() - free the CtrlHandles structure allocated
 
177
 * by nv_alloc_ctrl_handles()
 
178
 */
 
179
 
 
180
void nv_free_ctrl_handles(CtrlHandles *h)
 
181
{
 
182
    int i;
 
183
 
 
184
    if (!h) return;
 
185
 
 
186
    if (h->display) free(h->display);
 
187
 
 
188
    if (h->dpy) {
 
189
        
 
190
        for (i = 0; i < h->num_screens; i++) {
 
191
            NvCtrlAttributeClose(h->h[i]);
 
192
            if (h->screen_names[i]) free(h->screen_names[i]);
 
193
        }
 
194
        
 
195
        if (h->d) free(h->d);
 
196
        if (h->h) free(h->h);
 
197
        if (h->screen_names) free(h->screen_names);
 
198
        
 
199
        XCloseDisplay(h->dpy);
 
200
    }
 
201
    
 
202
    free(h);
 
203
    
 
204
} /* nv_free_ctrl_handles() */
 
205
 
 
206
 
 
207
 
 
208
/*
 
209
 * process_attribute_queries() - parse the list of queries, and
 
210
 * call NvCtrlProcessParsedAttribute() to process each query.
 
211
 *
 
212
 * If any errors are encountered, an error message is printed and
 
213
 * NV_FALSE is returned.  Otherwise, NV_TRUE is returned.
 
214
 *
 
215
 * XXX rather than call nv_alloc_ctrl_handles()/nv_free_ctrl_handles()
 
216
 * for every query, we should share the code in
 
217
 * process_config_file_attributes() to collapse the list of handles.
 
218
 */
 
219
 
 
220
static int process_attribute_queries(int num, char **queries,
 
221
                                     const char *display_name)
 
222
{
 
223
    int query, ret, val;
 
224
    ParsedAttribute a;
 
225
    CtrlHandles *h;
 
226
    
 
227
    val = NV_FALSE;
 
228
    
 
229
    /* loop over each requested query */
 
230
 
 
231
    for (query = 0; query < num; query++) {
 
232
        
 
233
        /* special case the "all" query */
 
234
 
 
235
        if (nv_strcasecmp(queries[query], "all")) {
 
236
            query_all(display_name);
 
237
            continue;
 
238
        }
 
239
        
 
240
        /* call the parser to parse queries[query] */
 
241
 
 
242
        ret = nv_parse_attribute_string(queries[query], NV_PARSER_QUERY, &a);
 
243
        if (ret != NV_PARSER_STATUS_SUCCESS) {
 
244
            nv_error_msg("Error parsing query '%s' (%s).",
 
245
                         queries[query], nv_parse_strerror(ret));
 
246
            goto done;
 
247
        }
 
248
        
 
249
        /* make sure we have a display */
 
250
 
 
251
        nv_assign_default_display(&a, display_name);
 
252
 
 
253
        /* allocate the CtrlHandles */
 
254
 
 
255
        h = nv_alloc_ctrl_handles(a.display);
 
256
 
 
257
        /* call the processing engine to process the parsed query */
 
258
 
 
259
        ret = nv_process_parsed_attribute(&a, h, NV_FALSE, NV_FALSE,
 
260
                                          "in query '%s'", queries[query]);
 
261
        /* free the CtrlHandles */
 
262
 
 
263
        nv_free_ctrl_handles(h);
 
264
 
 
265
        if (ret == NV_FALSE) goto done;
 
266
        
 
267
    } /* query */
 
268
 
 
269
    val = NV_TRUE;
 
270
    
 
271
 done:
 
272
    
 
273
    return val;
 
274
    
 
275
} /* process_attribute_queries() */
 
276
 
 
277
 
 
278
 
 
279
/*
 
280
 * process_attribute_assignments() - parse the list of
 
281
 * assignments, and call nv_process_parsed_attribute() to process
 
282
 * each assignment.
 
283
 *
 
284
 * If any errors are encountered, an error message is printed and
 
285
 * NV_FALSE is returned.  Otherwise, NV_TRUE is returned.
 
286
 *
 
287
 * XXX rather than call nv_alloc_ctrl_handles()/nv_free_ctrl_handles()
 
288
 * for every assignment, we should share the code in
 
289
 * process_config_file_attributes() to collapse the list of handles.
 
290
 */
 
291
 
 
292
static int process_attribute_assignments(int num, char **assignments,
 
293
                                         const char *display_name)
 
294
{
 
295
    int assignment, ret, val;
 
296
    ParsedAttribute a;
 
297
    CtrlHandles *h;
 
298
 
 
299
    val = NV_FALSE;
 
300
 
 
301
    /* loop over each requested assignment */
 
302
 
 
303
    for (assignment = 0; assignment < num; assignment++) {
 
304
        
 
305
        /* call the parser to parse assignments[assignment] */
 
306
 
 
307
        ret = nv_parse_attribute_string(assignments[assignment],
 
308
                                        NV_PARSER_ASSIGNMENT, &a);
 
309
 
 
310
        if (ret != NV_PARSER_STATUS_SUCCESS) {
 
311
            nv_error_msg("Error parsing assignment '%s' (%s).",
 
312
                         assignments[assignment], nv_parse_strerror(ret));
 
313
            goto done;
 
314
        }
 
315
        
 
316
        /* make sure we have a display */
 
317
 
 
318
        nv_assign_default_display(&a, display_name);
 
319
 
 
320
        /* allocate the CtrlHandles */
 
321
 
 
322
        h = nv_alloc_ctrl_handles(a.display);
 
323
        
 
324
        /* call the processing engine to process the parsed assignment */
 
325
 
 
326
        ret = nv_process_parsed_attribute(&a, h, NV_TRUE, NV_TRUE,
 
327
                                          "in assignment '%s'",
 
328
                                          assignments[assignment]);
 
329
        /* free the CtrlHandles */
 
330
 
 
331
        nv_free_ctrl_handles(h);
 
332
 
 
333
        if (ret == NV_FALSE) goto done;
 
334
 
 
335
    } /* assignment */
 
336
 
 
337
    val = NV_TRUE;
 
338
 
 
339
 done:
 
340
 
 
341
    return val;
 
342
 
 
343
} /* nv_process_attribute_assignments() */
 
344
 
 
345
 
 
346
 
 
347
/*
 
348
 * validate_value() - query the valid values for the specified
 
349
 * attribute, and check that the value to be assigned is valid.
 
350
 */
 
351
 
 
352
static int validate_value(CtrlHandles *h, ParsedAttribute *a, uint32 d,
 
353
                          int screen, char *whence)
 
354
{
 
355
    int bad_val = NV_FALSE;
 
356
    NVCTRLAttributeValidValuesRec valid;
 
357
    ReturnStatus status;
 
358
    char d_str[256];
 
359
    char *tmp_d_str;
 
360
 
 
361
    status = NvCtrlGetValidDisplayAttributeValues(h->h[screen], d,
 
362
                                                  a->attr, &valid);
 
363
   
 
364
    if (status != NvCtrlSuccess) {
 
365
        nv_error_msg("Unable to query valid values for attribute %s (%s).",
 
366
                     a->name, NvCtrlAttributesStrError(status));
 
367
        return NV_FALSE;
 
368
    }
 
369
    
 
370
    if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) {
 
371
        tmp_d_str = display_device_mask_to_display_device_name(d);
 
372
        sprintf(d_str, ", display device: %s", tmp_d_str);
 
373
        free(tmp_d_str);
 
374
    } else {
 
375
        d_str[0] = '\0';
 
376
    }
 
377
    
 
378
    switch (valid.type) {
 
379
    case ATTRIBUTE_TYPE_INTEGER:
 
380
    case ATTRIBUTE_TYPE_BITMASK:
 
381
        /* don't do any checks on integer or bitmask values */
 
382
        break;
 
383
    case ATTRIBUTE_TYPE_BOOL:
 
384
        if ((a->val < 0) || (a->val > 1)) {
 
385
            bad_val = NV_TRUE;
 
386
        }
 
387
        break;
 
388
    case ATTRIBUTE_TYPE_RANGE:
 
389
        if ((a->val < valid.u.range.min) || (a->val > valid.u.range.max)) {
 
390
            bad_val = NV_TRUE;
 
391
        }
 
392
        break;
 
393
    case ATTRIBUTE_TYPE_INT_BITS:
 
394
        if ((a->val > 31) || (a->val < 0) ||
 
395
            ((valid.u.bits.ints & (1<<a->val)) == 0)) {
 
396
            bad_val = NV_TRUE;
 
397
        }
 
398
        break;
 
399
    default:
 
400
        bad_val = NV_TRUE;
 
401
        break;
 
402
    }
 
403
 
 
404
    if (bad_val) {
 
405
        nv_warning_msg("The value %d for attribute '%s' (%s%s) "
 
406
                       "specified %s is invalid.",
 
407
                       a->val, a->name, h->screen_names[screen],
 
408
                       d_str, whence);
 
409
        print_valid_values(a->name, valid);
 
410
        return NV_FALSE;
 
411
    }
 
412
    return NV_TRUE;
 
413
 
 
414
} /* validate_value() */
 
415
 
 
416
 
 
417
 
 
418
/*
 
419
 * print_valid_values() - prints the valid values for the specified
 
420
 * attribute.
 
421
 */
 
422
 
 
423
static void print_valid_values(char *name, NVCTRLAttributeValidValuesRec valid)
 
424
{
 
425
    int bit, first, last;
 
426
    char str[256];
 
427
    char *c;
 
428
 
 
429
#define INDENT "    "
 
430
 
 
431
    switch (valid.type) {
 
432
    case ATTRIBUTE_TYPE_INTEGER:
 
433
        nv_msg(INDENT, "'%s' is an integer attribute.", name);
 
434
        break;
 
435
        
 
436
    case ATTRIBUTE_TYPE_BITMASK:
 
437
        nv_msg(INDENT, "'%s' is a bitmask attribute.", name);
 
438
        break;
 
439
        
 
440
    case ATTRIBUTE_TYPE_BOOL:
 
441
        nv_msg(INDENT, "'%s' is a boolean attribute; valid values are: "
 
442
               "1 (on/true) and 0 (off/false).", name);
 
443
        break;
 
444
        
 
445
    case ATTRIBUTE_TYPE_RANGE:
 
446
        nv_msg(INDENT, "The valid values for '%s' are in the range "
 
447
               "%d - %d (inclusive).", name,
 
448
               valid.u.range.min, valid.u.range.max);
 
449
        break;
 
450
 
 
451
    case ATTRIBUTE_TYPE_INT_BITS:
 
452
        first = last = -1;
 
453
 
 
454
        /* scan through the bitmask once to get first and last */
 
455
 
 
456
        for (bit = 0; bit < 32; bit++) {
 
457
            if (valid.u.bits.ints & (1 << bit)) {
 
458
                if (first == -1) first = bit;
 
459
                last = bit;
 
460
            }
 
461
        }
 
462
 
 
463
        /* now, scan through the bitmask again, building the string */
 
464
 
 
465
        str[0] = '\0';
 
466
        c = str;
 
467
        for (bit = 0; bit < 32; bit++) {
 
468
            if (valid.u.bits.ints & (1 << bit)) {
 
469
                if (bit == first) {
 
470
                    c += sprintf (c, "%d", bit);
 
471
                } else if (bit == last) {
 
472
                    c += sprintf (c, " and %d", bit);
 
473
                } else {
 
474
                    c += sprintf (c, ", %d", bit);
 
475
                }
 
476
            }
 
477
        }
 
478
        
 
479
        nv_msg(INDENT, "Valid values for '%s' are: %s.", name, str);
 
480
        break;
 
481
    }
 
482
 
 
483
    if (!(valid.permissions & ATTRIBUTE_TYPE_WRITE)) {
 
484
        nv_msg(INDENT, "'%s' is a read-only attribute.", name);
 
485
    }
 
486
 
 
487
    if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) {
 
488
        nv_msg(INDENT, "'%s' is display device specific.", name);
 
489
    }
 
490
   
 
491
#undef INDENT
 
492
 
 
493
} /* print_valid_values() */
 
494
 
 
495
 
 
496
 
 
497
/*
 
498
 * query_all() - loop through all screens, and query all attributes
 
499
 * for those screens.  The current attribute values for all display
 
500
 * devices on all screens are printed, along with the valid values for
 
501
 * each attribute.
 
502
 *
 
503
 * If an error occurs, an error message is printed and NV_FALSE is
 
504
 * returned; if successful, NV_TRUE is returned.
 
505
 */
 
506
 
 
507
static int query_all(const char *display_name)
 
508
{
 
509
    int bit, entry, screen, val;
 
510
    uint32 mask;
 
511
    ReturnStatus status;
 
512
    AttributeTableEntry *a;
 
513
    char *tmp_d_str;
 
514
    const char *fmt, *fmt_display;
 
515
    NVCTRLAttributeValidValuesRec valid;
 
516
    CtrlHandles *h;
 
517
 
 
518
    static const char *__fmt_str_int =
 
519
        "Attribute '%s' (screen: %s): %d.";
 
520
    static const char *__fmt_str_int_display =
 
521
        "Attribute '%s' (screen: %s; display: %s): %d.";
 
522
    static const char *__fmt_str_hex =
 
523
        "Attribute '%s' (screen: %s): 0x%08x.";
 
524
    static const char *__fmt_str_hex_display =
 
525
        "Attribute '%s' (screen: %s; display: %s): 0x%08x.";
 
526
    
 
527
    h = nv_alloc_ctrl_handles(display_name);
 
528
 
 
529
#define INDENT "  "
 
530
    
 
531
    for (screen = 0; screen < h->num_screens; screen++) {
 
532
 
 
533
        if (!h->h[screen]) continue;
 
534
 
 
535
        nv_msg(NULL, "Attributes for %s:", h->screen_names[screen]);
 
536
 
 
537
        for (entry = 0; attributeTable[entry].name; entry++) {
 
538
 
 
539
            a = &attributeTable[entry];
 
540
            
 
541
            /* skip the color attributes */
 
542
 
 
543
            if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) continue;
 
544
 
 
545
            for (bit = 0; bit < 24; bit++) {
 
546
                mask = 1 << bit;
 
547
 
 
548
                if ((h->d[screen] & mask) == 0x0) continue;
 
549
                
 
550
                status =
 
551
                    NvCtrlGetValidDisplayAttributeValues(h->h[screen], mask,
 
552
                                                         a->attr, &valid);
 
553
 
 
554
                if (status == NvCtrlAttributeNotAvailable) goto exit_bit_loop;
 
555
                
 
556
                if (status != NvCtrlSuccess) {
 
557
                    nv_error_msg("Error while querying valid values for "
 
558
                                 "attribute '%s' on %s (%s).",
 
559
                                 a->name, h->screen_names[screen],
 
560
                                 NvCtrlAttributesStrError(status));
 
561
                    goto exit_bit_loop;
 
562
                }
 
563
 
 
564
                status = NvCtrlGetDisplayAttribute(h->h[screen], mask,
 
565
                                                   a->attr, &val);
 
566
 
 
567
                if (status == NvCtrlAttributeNotAvailable) goto exit_bit_loop;
 
568
 
 
569
                if (status != NvCtrlSuccess) {
 
570
                    nv_error_msg("Error while querying attribute '%s' "
 
571
                                 "on %s (%s).",
 
572
                                 a->name, h->screen_names[screen],
 
573
                                 NvCtrlAttributesStrError(status));
 
574
                    goto exit_bit_loop;
 
575
                }
 
576
                
 
577
                if (valid.type == ATTRIBUTE_TYPE_BITMASK) {
 
578
                    fmt = __fmt_str_hex;
 
579
                    fmt_display = __fmt_str_hex_display;
 
580
                } else {
 
581
                    fmt = __fmt_str_int;
 
582
                    fmt_display = __fmt_str_int_display;
 
583
                }
 
584
 
 
585
                if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) {
 
586
                    
 
587
                    tmp_d_str =
 
588
                        display_device_mask_to_display_device_name(mask);
 
589
                    
 
590
                    nv_msg(INDENT, fmt_display, a->name,
 
591
                           h->screen_names[screen], tmp_d_str, val);
 
592
                    
 
593
                    free(tmp_d_str);
 
594
 
 
595
                    print_valid_values(a->name, valid);
 
596
 
 
597
                    continue;
 
598
 
 
599
                } else {
 
600
                    nv_msg(INDENT, fmt, a->name, h->screen_names[screen], val);
 
601
 
 
602
                    print_valid_values(a->name, valid);
 
603
 
 
604
                    /* fall through to exit_bit_loop */
 
605
                }
 
606
                
 
607
            exit_bit_loop:
 
608
 
 
609
                bit = 25; /* XXX force us out of the display device loop */
 
610
                
 
611
            } /* bit */
 
612
            
 
613
        } /* entry */
 
614
        
 
615
    } /* screen */
 
616
 
 
617
#undef INDENT
 
618
 
 
619
    nv_free_ctrl_handles(h);
 
620
 
 
621
    return NV_TRUE;
 
622
 
 
623
} /* query_all() */
 
624
 
 
625
 
 
626
 
 
627
/*
 
628
 * process_parsed_attribute_internal() - this function does the
 
629
 * actually attribute processing for NvCtrlProcessParsedAttribute().
 
630
 *
 
631
 * If an error occurs, an error message is printed and NV_FALSE is
 
632
 * returned; if successful, NV_TRUE is returned.
 
633
 */
 
634
 
 
635
static int process_parsed_attribute_internal(CtrlHandles *h,
 
636
                                             ParsedAttribute *a, uint32 d,
 
637
                                             int screen, int assign,
 
638
                                             int verbose, char *whence,
 
639
                                             NVCTRLAttributeValidValuesRec
 
640
                                             valid)
 
641
{
 
642
    ReturnStatus status;
 
643
    char str[32], *tmp_d_str;
 
644
    int ret;
 
645
    
 
646
    if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) {
 
647
        tmp_d_str = display_device_mask_to_display_device_name(d);
 
648
        sprintf(str, ", display device: %s", tmp_d_str);
 
649
        free(tmp_d_str);
 
650
    } else {
 
651
        str[0] = '\0';
 
652
    }
 
653
 
 
654
    if (assign) {
 
655
        ret = validate_value(h, a, d, screen, whence);
 
656
        if (!ret) return NV_FALSE;
 
657
 
 
658
        status = NvCtrlSetDisplayAttribute(h->h[screen], d, a->attr, a->val);
 
659
        if (status != NvCtrlSuccess) {
 
660
            nv_error_msg("Error assigning value %d to attribute '%s' "
 
661
                         "(%s%s) as specified %s (%s).",
 
662
                         a->val, a->name, h->screen_names[screen], str, whence,
 
663
                         NvCtrlAttributesStrError(status));
 
664
            return NV_FALSE;
 
665
        }
 
666
        
 
667
        if (verbose) {
 
668
            nv_msg("  ", "Attribute '%s' (%s%s) assigned value %d.",
 
669
                   a->name, h->screen_names[screen], str, a->val);
 
670
        }
 
671
 
 
672
    } else { /* query */
 
673
        
 
674
        status = NvCtrlGetDisplayAttribute(h->h[screen], d, a->attr, &a->val);
 
675
 
 
676
        if (status == NvCtrlAttributeNotAvailable) {
 
677
            nv_warning_msg("Error querying attribute '%s' specified %s; "
 
678
                           "'%s' is not available on %s%s.",
 
679
                           a->name, whence, a->name,
 
680
                           h->screen_names[screen], str);
 
681
        } else if (status != NvCtrlSuccess) {
 
682
            nv_error_msg("Error while querying attribute '%s' "
 
683
                         "(%s%s) specified %s (%s).",
 
684
                         a->name, h->screen_names[screen], str, whence,
 
685
                         NvCtrlAttributesStrError(status));
 
686
            return NV_FALSE;
 
687
        } else {
 
688
            nv_msg("  ", "Attribute '%s' (%s%s): %d.",
 
689
                   a->name, h->screen_names[screen], str, a->val);
 
690
            print_valid_values(a->name, valid);
 
691
        }
 
692
    }
 
693
 
 
694
    return NV_TRUE;
 
695
 
 
696
} /* process_parsed_attribute_internal() */
 
697
 
 
698
 
 
699
 
 
700
/*
 
701
 * nv_process_parsed_attribute() - this is the processing engine for
 
702
 * all parsed attributes.
 
703
 *
 
704
 * A parsed attribute may or may not specify an X screen; if an X
 
705
 * screen was specified, we validate that screen and process the
 
706
 * attribute just for that screen.  If a screen was not specified, we
 
707
 * process the attribute for all valid screens.
 
708
 *
 
709
 * A parsed attribute may or may not specify one or more display
 
710
 * devices.  For attributes that require that a display device be
 
711
 * specified: if a display device mask is specified, we validate it
 
712
 * and process the attribute just for the display devices in the mask.
 
713
 * If a display device mask was not specified, then we process the
 
714
 * attribute for all enabled display devices on each of the screens
 
715
 * that have been requested.
 
716
 *
 
717
 * "Processing" a parsed attribute means either querying for the
 
718
 * current value of the attribute on all requested screens and display
 
719
 * devices (see above), or assigning the attribute on all requested
 
720
 * screens and display devices (see above).
 
721
 *
 
722
 * The majority of the work (determining which screens, which display
 
723
 * devices) is the same, regardless of what sort of processing we
 
724
 * actually need to do (thus this shared function).
 
725
 *
 
726
 * To accomodate the differences in processing needed for each of the
 
727
 * callers of this function, the paramenters 'assign' and 'verbose'
 
728
 * are used; if assign is TRUE, then the attribute will be assigned
 
729
 * during processing, otherwise it will be queried.  If verbose is
 
730
 * TRUE, then a message will be printed out during each assignment (or
 
731
 * query).
 
732
 *
 
733
 * The CtrlHandles argument contains an array of
 
734
 * NvCtrlAttributeHandle's (one per X screen on this X server), as
 
735
 * well as the number of X screens, an array of enabled display
 
736
 * devices for each screen, and a string description of each screen.
 
737
 *
 
738
 * The whence_fmt and following varargs are used by the callee to
 
739
 * describe where the attribute came from.  A whence string should be
 
740
 * something like "on line 12 of config file ~/.nvidia-settings-rc" or
 
741
 * "in query ':0.0/fsaa'".  Whence is used in the case of error to
 
742
 * indicate where the error came from.
 
743
 *
 
744
 * If successful, the processing determined by 'assign' and 'verbose'
 
745
 * will be done and NV_TRUE will be returned.  If an error occurs, an
 
746
 * error message will be printed and NV_FALSE will be returned.
 
747
 */
 
748
 
 
749
int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
 
750
                                int assign, int verbose,
 
751
                                char *whence_fmt, ...)
 
752
{
 
753
    int screen, start_screen, end_screen, bit, ret, val;
 
754
    char *whence, *tmp_d_str0, *tmp_d_str1;
 
755
    uint32 display_devices, mask;
 
756
    va_list ap;
 
757
    ReturnStatus status;
 
758
    NVCTRLAttributeValidValuesRec valid;
 
759
    
 
760
    val = NV_FALSE;
 
761
 
 
762
    /* build the description */
 
763
 
 
764
    va_start(ap, whence_fmt);
 
765
    whence = nv_build_vararg_string(whence_fmt, ap);
 
766
    va_end(ap);
 
767
    
 
768
    if (!whence) whence = strdup("\0");
 
769
 
 
770
    /* if we don't have a Display connection, abort now */
 
771
 
 
772
    if (!h->dpy) {
 
773
        nv_error_msg("Unable to %s attribute %s specified %s (no Display "
 
774
                     "connection).", assign ? "assign" : "query",
 
775
                     a->name, whence);
 
776
        goto done;
 
777
    }
 
778
    
 
779
    /* if a screen was specified, make sure it is valid */
 
780
 
 
781
    if (a->flags & NV_PARSER_HAS_X_SCREEN) {
 
782
        
 
783
        if (a->screen >= h->num_screens) {
 
784
            if (h->num_screens == 1) {
 
785
                nv_error_msg("Invalid X screen %d specified %s "
 
786
                             "(there is only 1 screen on this Display).",
 
787
                             a->screen, whence);
 
788
            } else {
 
789
                nv_error_msg("Invalid X screen %d specified %s "
 
790
                             "(there are only %d screens on this Display).",
 
791
                             a->screen, whence, h->num_screens);
 
792
            }
 
793
            goto done;
 
794
        }
 
795
 
 
796
        if (!h->h[a->screen]) {
 
797
            nv_error_msg("Invalid screen %d specified %s "
 
798
                         "(NV-CONTROL extension not supported on "
 
799
                         "screen %d).", a->screen, whence, a->screen);
 
800
        }
 
801
        
 
802
        /*
 
803
         * assign start_screen and end_screen such that the screen
 
804
         * loop only uses this screen.
 
805
         */
 
806
        
 
807
        start_screen = a->screen;
 
808
        end_screen = a->screen + 1;
 
809
    } else {
 
810
        
 
811
        /*
 
812
         * no screen was specified; assign start_screen and end_screen
 
813
         * such that we loop over all the screens
 
814
         */
 
815
        
 
816
        start_screen = 0;
 
817
        end_screen = h->num_screens;
 
818
    }
 
819
 
 
820
    /* loop over the requested screens */
 
821
 
 
822
    for (screen = start_screen; screen < end_screen; screen++) {
 
823
            
 
824
        if (!h->h[screen]) continue; /* no handle on this screen; skip */
 
825
 
 
826
        if (a->flags & NV_PARSER_HAS_DISPLAY_DEVICE) {
 
827
 
 
828
            /* Expand any wildcards in the display device mask */
 
829
        
 
830
            display_devices = expand_display_device_mask_wildcards
 
831
                (a->display_device_mask, h->d[screen]);
 
832
            
 
833
            if ((display_devices == 0) || (display_devices & ~h->d[screen])) {
 
834
 
 
835
                /*
 
836
                 * use a->display_device_mask rather than
 
837
                 * display_devices when building the string (so that
 
838
                 * display_device_mask_to_display_device_name() can
 
839
                 * use wildcards if present).
 
840
                 */
 
841
 
 
842
                tmp_d_str0 = display_device_mask_to_display_device_name
 
843
                    (a->display_device_mask);
 
844
                tmp_d_str1 = display_device_mask_to_display_device_name
 
845
                    (h->d[screen]);
 
846
 
 
847
                nv_error_msg("Invalid display device %s specified "
 
848
                             "%s (the currently enabled display devices "
 
849
                             "are %s on %s).",
 
850
                             tmp_d_str0, whence, tmp_d_str1,
 
851
                             h->screen_names[screen]);
 
852
                free(tmp_d_str0);
 
853
                free(tmp_d_str1);
 
854
                
 
855
                goto done;
 
856
            }
 
857
            
 
858
        } else {
 
859
            
 
860
            display_devices = h->d[screen];
 
861
        }
 
862
        
 
863
        /* special case the color attributes */
 
864
        
 
865
        if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
 
866
            float v[3];
 
867
            if (!assign) {
 
868
                nv_error_msg("Cannot query attribute '%s'", a->name);
 
869
                goto done;
 
870
            }
 
871
            
 
872
            /*
 
873
             * assign fval to all values in the array; a->attr will
 
874
             * tell NvCtrlSetColorAttributes() which indices in the
 
875
             * array to use
 
876
             */
 
877
 
 
878
            v[0] = v[1] = v[2] = a->fval;
 
879
 
 
880
            status = NvCtrlSetColorAttributes(h->h[screen], v, v, v, a->attr);
 
881
            if (status != NvCtrlSuccess) {
 
882
                nv_error_msg("Error assigning %f to attribute '%s' on %s "
 
883
                             "specified %s (%s)", a->fval, a->name,
 
884
                             h->screen_names[screen], whence,
 
885
                             NvCtrlAttributesStrError(status));
 
886
                goto done;
 
887
            }
 
888
 
 
889
            continue;
 
890
        }
 
891
 
 
892
        for (bit = 0; bit < 24; bit++) {
 
893
            
 
894
            mask = (1 << bit);
 
895
 
 
896
            if ((mask & display_devices) == 0x0) continue;
 
897
            
 
898
            status = NvCtrlGetValidDisplayAttributeValues(h->h[screen], mask,
 
899
                                                          a->attr, &valid);
 
900
            if (status != NvCtrlSuccess) {
 
901
                nv_error_msg("Error querying valid values for attribute "
 
902
                             "'%s' on %s specified %s (%s).",
 
903
                             a->name, h->screen_names[screen], whence,
 
904
                             NvCtrlAttributesStrError(status));
 
905
                goto done;
 
906
            }
 
907
            
 
908
            /*
 
909
             * if this attribute is going to be assigned, then check
 
910
             * that the attribute is writable; if it's not, give up
 
911
             */
 
912
 
 
913
            if ((assign) && (!(valid.permissions & ATTRIBUTE_TYPE_WRITE))) {
 
914
                nv_error_msg("The attribute '%s' specified %s cannot be "
 
915
                             "assigned (it is a read-only attribute).",
 
916
                             a->name, whence);
 
917
                goto done;
 
918
            }
 
919
            
 
920
            ret = process_parsed_attribute_internal(h, a, mask, screen,
 
921
                                                    assign, verbose,
 
922
                                                    whence, valid);
 
923
            if (ret == NV_FALSE) goto done;
 
924
            
 
925
            if (!(valid.permissions & ATTRIBUTE_TYPE_DISPLAY)) bit = 25;
 
926
 
 
927
        } /* bit */
 
928
        
 
929
    } /* screen */
 
930
 
 
931
    val = NV_TRUE;
 
932
    
 
933
 done:
 
934
    if (whence) free(whence);
 
935
    return val;
 
936
 
 
937
} /* nv_process_parsed_attribute() */