mirror of
git://nv-tegra.nvidia.com/tegra/gfx-src/nv-xconfig.git
synced 2025-12-22 09:22:53 +03:00
22a5c807291792a264b5acca7ff6d199468890b8 - nvidia-xconfig-35.6.2/Makefile 4cc77b90af91e615a64ae04893fdffa7939db84c - nvidia-xconfig-35.6.2/COPYING f14e9577e537037d4778d490ef70f13b0e94a70a - nvidia-xconfig-35.6.2/option_table.h 647e7896275a1113ec99352d573823a05001f57e - nvidia-xconfig-35.6.2/lscf.c 1e39095238886dfc6a69f7ec750e10c05a93e7d1 - nvidia-xconfig-35.6.2/nvidia-xconfig.1.m4 a5ad539267b73169480e7898b284823639c4db3a - nvidia-xconfig-35.6.2/tree.c b3d0f9f27c4d9cb7940d04e1dd387d357a16024c - nvidia-xconfig-35.6.2/nvidia-xconfig.c 46f2ea329459b0b16cb36cc14cec0de737d0963e - nvidia-xconfig-35.6.2/options.c 6f6f68f976250f2646450e571f9ab2d7eee1ac80 - nvidia-xconfig-35.6.2/nvidia-cfg.h 913b088cb559f31e09a1baf89d85d75cb43079b4 - nvidia-xconfig-35.6.2/nvidia-xconfig.h bfa37f78ba458f14a1865bbf3f67eb84987a7e1c - nvidia-xconfig-35.6.2/extract_edids.c d37da5a118e0418b267a48d05fd144611316b42c - nvidia-xconfig-35.6.2/gen-manpage-opts.c 41bcac41393c9a465c30c07cf1ab386647a16687 - nvidia-xconfig-35.6.2/util.c 9b0c02164398be2795fea7cb13c9e1b062d24bfb - nvidia-xconfig-35.6.2/query_gpu_info.c c946eefad99cec9366d8abbd4e45c5d138d3b7be - nvidia-xconfig-35.6.2/make_usable.c 10edc2c301fd331439b38d001c0df41669c238b2 - nvidia-xconfig-35.6.2/multiple_screens.c c7b8d8ca0f7c9dcc2cdca4f8e77d1122c71892ef - nvidia-xconfig-35.6.2/XF86Config-parser/Read.c a9bc06f33bf525c2b08be2dc3cd64a59c4c7946d - nvidia-xconfig-35.6.2/XF86Config-parser/Configint.h 2022a4a3c2a1b23a67ae74f50a3849f5f3a45e4b - nvidia-xconfig-35.6.2/XF86Config-parser/Keyboard.c 83b0a8efd6a508db54995688ab353591bdb242a2 - nvidia-xconfig-35.6.2/XF86Config-parser/Flags.c e67d630ef396ab7d34524c333f3a77fc42ba8fc6 - nvidia-xconfig-35.6.2/XF86Config-parser/configProcs.h f3d611bdbddfa64675a0810ef81dada57e224bcd - nvidia-xconfig-35.6.2/XF86Config-parser/Extensions.c 5ffb2caa5077a2e6ec1c5ece807e71503fb2fbce - nvidia-xconfig-35.6.2/XF86Config-parser/Module.c 7344be997921dec57959691e986763ee686888d5 - nvidia-xconfig-35.6.2/XF86Config-parser/Device.c 33211ca0a10f50e2c87b9e8feef6c1ab381b57a1 - nvidia-xconfig-35.6.2/XF86Config-parser/DRI.c 953b945f3b117d6fb44f1f738af17b6380a9ec72 - nvidia-xconfig-35.6.2/XF86Config-parser/Monitor.c 6c210ad0eaee1db3fec48ff01746cb054b4f9aaa - nvidia-xconfig-35.6.2/XF86Config-parser/Video.c 4407207cf890539dc604cff5b834c994b307729a - nvidia-xconfig-35.6.2/XF86Config-parser/Write.c de1c758e29f217e1a99e4c076d54ac84bce98b18 - nvidia-xconfig-35.6.2/XF86Config-parser/Screen.c c66a0a141e25e31b568fb9df41f17d7fb9e6d3b9 - nvidia-xconfig-35.6.2/XF86Config-parser/xf86Parser.h 9cbc29da282aa957f28b7fc83caf1e3b19ee2a52 - nvidia-xconfig-35.6.2/XF86Config-parser/Vendor.c 18711ff932af2202869a30f3b32d6d7fe7811c84 - nvidia-xconfig-35.6.2/XF86Config-parser/Layout.c cda3a4ab05bf48ba28af35b5c4c632e968afc7fa - nvidia-xconfig-35.6.2/XF86Config-parser/Util.c ec19d673a6a7d1d8f855f2d32d3e8f63046c3625 - nvidia-xconfig-35.6.2/XF86Config-parser/Files.c ac878b26ded86a3c502a6a81fc4c4a96162afefb - nvidia-xconfig-35.6.2/XF86Config-parser/Merge.c 0a274c4bc54b6ae0f6d009e443bda0cb033d66b5 - nvidia-xconfig-35.6.2/XF86Config-parser/Pointer.c 3f2238c88d737bd329a9bca1ac4b0bcf77bb9ac2 - nvidia-xconfig-35.6.2/XF86Config-parser/xf86tokens.h 45ceb0129668346ae3e52d81bb6e2f97efadf9d0 - nvidia-xconfig-35.6.2/XF86Config-parser/Input.c 4d9b03ea3badceb6bdfdf6589e6731140ec44079 - nvidia-xconfig-35.6.2/XF86Config-parser/Generate.c 04efe162cf6d97882f2bb87f3712d9a65c2320f3 - nvidia-xconfig-35.6.2/XF86Config-parser/Scan.c 5d55b94375c2055cfa1578e4c7f34c90e63a33f7 - nvidia-xconfig-35.6.2/common-utils/gen-manpage-opts-helper.c 384e36102dcd08ed4c5de05b5e3b8a7cdb2e257d - nvidia-xconfig-35.6.2/common-utils/nvgetopt.c dc2678d8a9d794a4b2b2718fce57ec087f21f54b - nvidia-xconfig-35.6.2/common-utils/common-utils.h aac5cbf0e68e1da4e646c316a7c0e620304ee16b - nvidia-xconfig-35.6.2/common-utils/msg.c e572cac43202f6c2af1c80b9e3901215126093ed - nvidia-xconfig-35.6.2/common-utils/nvgetopt.h 8a346196b052cfb1e06dd83d2ad1fe71e928d2b3 - nvidia-xconfig-35.6.2/common-utils/common-utils.c 1654638c567bc7f2bd70b54d807b498ab14c1061 - nvidia-xconfig-35.6.2/common-utils/nvpci-utils.h 8259a24058c714629f9819cc8c830ea9b202bb27 - nvidia-xconfig-35.6.2/common-utils/gen-manpage-opts-helper.h 524990f5497f9bbeb3d148b5e7dc8d2267c3163d - nvidia-xconfig-35.6.2/common-utils/nvpci-utils.c abb5c1b445d9353f2d2840bda848cd16109710a4 - nvidia-xconfig-35.6.2/common-utils/msg.h Change-Id: I99682b72c725a16fef77ba060c57fd78b05ae428
1355 lines
37 KiB
C
1355 lines
37 KiB
C
/*
|
|
* nvidia-xconfig: A tool for manipulating X config files,
|
|
* specifically for use by the NVIDIA Linux graphics driver.
|
|
*
|
|
* Copyright (C) 2005 NVIDIA Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
|
*
|
|
*
|
|
* nvidia-xconfig.c
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <libgen.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "nvidia-xconfig.h"
|
|
#include "nvgetopt.h"
|
|
#include "msg.h"
|
|
|
|
#define TAB " "
|
|
#define BIGTAB " "
|
|
|
|
#define ORIG_SUFFIX ".nvidia-xconfig-original"
|
|
#define BACKUP_SUFFIX ".backup"
|
|
|
|
|
|
/*
|
|
* print_version() - print version information
|
|
*/
|
|
|
|
static void print_version(void)
|
|
{
|
|
nv_info_msg(NULL, "");
|
|
nv_info_msg(NULL, "%s", NV_ID_STRING);
|
|
nv_info_msg(TAB, "The NVIDIA X Configuration Tool.");
|
|
nv_info_msg(NULL, "");
|
|
nv_info_msg(TAB, "This program is used to manipulate X configuration files, "
|
|
"specifically to enable NVIDIA X driver functionality.");
|
|
nv_info_msg(NULL, "");
|
|
} /* print_version() */
|
|
|
|
|
|
static void print_summary(void)
|
|
{
|
|
nv_info_msg(NULL, "");
|
|
nv_info_msg(TAB, "In its normal operation, nvidia-xconfig finds the system "
|
|
"X configuration file (or generates a new X configuration "
|
|
"if it cannot find the system file), makes sure the "
|
|
"configuration is usable by the NVIDIA X driver, applies "
|
|
"any updates requested on the commandline, and writes the "
|
|
"new configuration to file.");
|
|
nv_info_msg(NULL, "");
|
|
nv_info_msg(TAB, "Please see the NVIDIA README for a description of NVIDIA "
|
|
"X configuration file options.");
|
|
nv_info_msg(NULL, "");
|
|
}
|
|
|
|
|
|
#include "option_table.h"
|
|
|
|
|
|
/*
|
|
* print_help() - loop through the __options[] table, and print the
|
|
* description of each option.
|
|
*/
|
|
|
|
static void print_help_helper(const char *name, const char *description)
|
|
{
|
|
nv_info_msg(TAB, "%s", name);
|
|
nv_info_msg(BIGTAB, "%s", description);
|
|
nv_info_msg(NULL, "");
|
|
}
|
|
|
|
static void print_help(int advanced)
|
|
{
|
|
unsigned int include_mask = 0;
|
|
|
|
print_version();
|
|
print_summary();
|
|
|
|
nv_info_msg(NULL, "");
|
|
nv_info_msg(NULL, "nvidia-xconfig [options]");
|
|
nv_info_msg(NULL, "");
|
|
|
|
if (!advanced) {
|
|
/* only print options with the ALWAYS flag */
|
|
include_mask |= NVGETOPT_HELP_ALWAYS;
|
|
}
|
|
|
|
nvgetopt_print_help(__options, include_mask, print_help_helper);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* parse_commandline() - malloc an Options structure, initialize it,
|
|
* and fill in any pertinent data from the commandline arguments
|
|
*/
|
|
|
|
static void parse_commandline(Options *op, int argc, char *argv[])
|
|
{
|
|
int c, boolval;
|
|
char *strval;
|
|
int intval, disable;
|
|
double doubleval;
|
|
|
|
|
|
while (1) {
|
|
|
|
c = nvgetopt(argc, argv, __options, &strval,
|
|
&boolval, &intval, &doubleval, &disable);
|
|
|
|
if (c == -1)
|
|
break;
|
|
|
|
/* catch the boolean options */
|
|
|
|
if ((c >= XCONFIG_BOOL_OPTION_START) &&
|
|
(c <= (XCONFIG_BOOL_OPTION_START + XCONFIG_BOOL_OPTION_COUNT))) {
|
|
|
|
if (!check_boolean_option(op, c - XCONFIG_BOOL_OPTION_START, boolval)) {
|
|
goto fail;
|
|
}
|
|
set_boolean_option(op, c - XCONFIG_BOOL_OPTION_START, boolval);
|
|
|
|
continue;
|
|
}
|
|
|
|
switch (c) {
|
|
|
|
case 'v': print_version(); exit(0); break;
|
|
case 'c': op->xconfig = strval; break;
|
|
case 'o': op->output_xconfig = strval; break;
|
|
case 't': op->tree = TRUE; break;
|
|
case 'T': op->post_tree = TRUE; break;
|
|
case 'h': print_help(FALSE); exit(0); break;
|
|
case 'A': print_help(TRUE); exit(0); break;
|
|
case 's': nv_set_verbosity(NV_VERBOSITY_WARNING); break;
|
|
case 'a': op->enable_all_gpus = TRUE; break;
|
|
case '1': op->only_one_screen = TRUE; break;
|
|
|
|
case 'd': op->depth = intval;
|
|
if ((op->depth != 8) &&
|
|
(op->depth != 15) &&
|
|
(op->depth != 16) &&
|
|
(op->depth != 24) &&
|
|
(op->depth != 30)) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid depth: %d.\n", op->depth);
|
|
fprintf(stderr, "\n");
|
|
goto fail;
|
|
}
|
|
break;
|
|
|
|
case LAYOUT_OPTION: op->layout = strval; break;
|
|
case SCREEN_OPTION: op->screen = strval; break;
|
|
case DEVICE_OPTION: op->device = strval; break;
|
|
case BUSID_OPTION:
|
|
if (GET_BOOL_OPTION(op->boolean_option_values, ENABLE_PRIME_OPTION)) {
|
|
fprintf(stderr, "Unable to disable BUSID with PRIME enabled.\n");
|
|
goto fail;
|
|
}
|
|
op->busid = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case X_PREFIX_OPTION: op->gop.x_project_root = strval; break;
|
|
|
|
case KEYBOARD_OPTION: op->gop.keyboard = strval; break;
|
|
case KEYBOARD_LIST_OPTION: op->keyboard_list = TRUE; break;
|
|
case KEYBOARD_DRIVER_OPTION: op->gop.keyboard_driver = strval; break;
|
|
|
|
case MOUSE_OPTION: op->gop.mouse = strval; break;
|
|
case MOUSE_LIST_OPTION: op->mouse_list = TRUE; break;
|
|
|
|
case NVIDIA_CFG_PATH_OPTION: op->nvidia_cfg_path = strval; break;
|
|
|
|
case FORCE_GENERATE_OPTION: op->force_generate = TRUE; break;
|
|
|
|
case ACPID_SOCKET_PATH_OPTION:
|
|
if (disable) {
|
|
op->acpid_socket_path = NV_DISABLE_STRING_OPTION;
|
|
} else {
|
|
op->acpid_socket_path = strval;
|
|
}
|
|
break;
|
|
|
|
case HANDLE_SPECIAL_KEYS_OPTION:
|
|
{
|
|
const char *valid_values[] = {
|
|
"Always",
|
|
"Never",
|
|
"WhenNeeded",
|
|
NULL,
|
|
};
|
|
|
|
int i;
|
|
|
|
if (disable) {
|
|
op->handle_special_keys = NV_DISABLE_STRING_OPTION;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; valid_values[i]; i++) {
|
|
if (!strcasecmp(strval, valid_values[i])) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valid_values[i]) {
|
|
op->handle_special_keys = strval;
|
|
} else {
|
|
fprintf(stderr, "Invalid HandleSpecialKeys option: %s.\n", strval);
|
|
goto fail;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case TRANSPARENT_INDEX_OPTION:
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
|
|
if (disable) {
|
|
op->transparent_index = -2;
|
|
break;
|
|
}
|
|
|
|
if (intval < 0 || intval > 255) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid transparent index: %d.\n", intval);
|
|
fprintf(stderr, "\n");
|
|
goto fail;
|
|
}
|
|
op->transparent_index = intval;
|
|
break;
|
|
|
|
case TV_STANDARD_OPTION:
|
|
|
|
{
|
|
const char* valid_values[] = {
|
|
"PAL-B",
|
|
"PAL-D",
|
|
"PAL-G",
|
|
"PAL-H",
|
|
"PAL-I",
|
|
"PAL-K1",
|
|
"PAL-M",
|
|
"PAL-N",
|
|
"PAL-NC",
|
|
"NTSC-J",
|
|
"NTSC-M",
|
|
"HD480i",
|
|
"HD480p",
|
|
"HD720p",
|
|
"HD1080i",
|
|
"HD1080p",
|
|
"HD576i",
|
|
"HD576p",
|
|
NULL
|
|
};
|
|
int i;
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
|
|
if (disable) {
|
|
op->tv_standard = NV_DISABLE_STRING_OPTION;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; valid_values[i]; i++) {
|
|
if (!strcasecmp(strval, valid_values[i]))
|
|
break;
|
|
}
|
|
|
|
if (valid_values[i]) {
|
|
op->tv_standard = strval;
|
|
} else {
|
|
fprintf(stderr, "Invalid TVStandard option: %s.\n", strval);
|
|
goto fail;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TV_OUT_FORMAT_OPTION:
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
|
|
if (disable) {
|
|
op->tv_out_format = NV_DISABLE_STRING_OPTION;
|
|
break;
|
|
}
|
|
|
|
if (!strcasecmp(strval, "SVIDEO")) {
|
|
op->tv_out_format = "SVIDEO";
|
|
} else if (!strcasecmp(strval, "COMPOSITE")) {
|
|
op->tv_out_format = "COMPOSITE";
|
|
} else {
|
|
fprintf(stderr, "Invalid TVOutFormat option: %s.\n", strval);
|
|
goto fail;
|
|
}
|
|
break;
|
|
|
|
case COOL_BITS_OPTION:
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
|
|
if (disable) {
|
|
op->cool_bits = -2;
|
|
break;
|
|
}
|
|
|
|
op->cool_bits = intval;
|
|
break;
|
|
|
|
case STEREO_OPTION:
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
|
|
if (disable) {
|
|
op->stereo = -2;
|
|
break;
|
|
}
|
|
|
|
if (intval < 0 || intval > 14) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid stereo: %d.\n", intval);
|
|
fprintf(stderr, "\n");
|
|
goto fail;
|
|
}
|
|
op->stereo = intval;
|
|
break;
|
|
|
|
case MODE_OPTION:
|
|
if (boolval) {
|
|
/* add this mode */
|
|
nv_text_rows_append(&op->add_modes, strval);
|
|
} else {
|
|
/* remove this mode */
|
|
nv_text_rows_append(&op->remove_modes, strval);
|
|
}
|
|
break;
|
|
|
|
case MODE_LIST_OPTION:
|
|
{
|
|
char *token;
|
|
token = strtok(strval, " ");
|
|
if (!token) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid Mode List string: %s.\n", strval);
|
|
fprintf(stderr, "\n");
|
|
goto fail;
|
|
}
|
|
do {
|
|
nv_text_rows_append(&op->add_modes_list, token);
|
|
token = strtok(NULL, " ");
|
|
} while (token != NULL);
|
|
|
|
break;
|
|
}
|
|
|
|
case REMOVE_MODE_OPTION:
|
|
nv_text_rows_append(&op->remove_modes, strval);
|
|
break;
|
|
|
|
case META_MODES_OPTION:
|
|
op->metamodes_str = strval;
|
|
break;
|
|
|
|
case MULTI_GPU_OPTION: /* fall through */
|
|
case SLI_OPTION:
|
|
{
|
|
const char* valid_values[] = {
|
|
"0",
|
|
"no",
|
|
"off",
|
|
"false",
|
|
"single",
|
|
"mosaic",
|
|
NULL
|
|
};
|
|
|
|
if (disable) {
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
strval = NV_DISABLE_STRING_OPTION;
|
|
|
|
} else {
|
|
|
|
/* check that the string is valid */
|
|
int i;
|
|
|
|
for (i = 0; valid_values[i]; i++) {
|
|
if (!strcasecmp(strval, valid_values[i]))
|
|
break;
|
|
}
|
|
|
|
if (!valid_values[i]) {
|
|
fprintf(stderr, "Invalid SLI option: %s.\n", strval);
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
if (c == MULTI_GPU_OPTION) {
|
|
op->multigpu = strval;
|
|
} else {
|
|
op->sli = strval;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PRESERVE_DRIVER_NAME_OPTION: op->preserve_driver = TRUE; break;
|
|
|
|
case DISABLE_SCF_OPTION: op->disable_scf = TRUE; break;
|
|
|
|
case QUERY_GPU_INFO_OPTION: op->query_gpu_info = TRUE; break;
|
|
|
|
case 'E':
|
|
op->extract_edids_from_file = strval;
|
|
break;
|
|
|
|
case EXTRACT_EDIDS_OUTPUT_FILE_OPTION:
|
|
op->extract_edids_output_file = strval;
|
|
break;
|
|
|
|
case NVIDIA_XINERAMA_INFO_ORDER_OPTION:
|
|
op->nvidia_xinerama_info_order =
|
|
disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case METAMODE_ORIENTATION_OPTION:
|
|
{
|
|
const char* valid_values[] = {
|
|
"RightOf",
|
|
"LeftOf",
|
|
"Above",
|
|
"Below",
|
|
"Clone",
|
|
NULL
|
|
};
|
|
int i;
|
|
|
|
if (disable) {
|
|
op->metamode_orientation = NV_DISABLE_STRING_OPTION;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; valid_values[i]; i++) {
|
|
if (!strcasecmp(strval, valid_values[i]))
|
|
break;
|
|
}
|
|
|
|
if (!valid_values[i]) {
|
|
fprintf(stderr, "Invalid MetaModeOrientation option: "
|
|
"\"%s\".\n", strval);
|
|
goto fail;
|
|
}
|
|
|
|
op->metamode_orientation = strval;
|
|
}
|
|
break;
|
|
|
|
case VIRTUAL_OPTION:
|
|
{
|
|
int ret, x, y;
|
|
|
|
if (disable) {
|
|
op->virtual.x = op->virtual.y = -1;
|
|
break;
|
|
}
|
|
|
|
ret = sscanf(strval, "%dx%d", &x, &y);
|
|
|
|
if (ret != 2) {
|
|
fprintf(stderr, "Invalid Virtual option: \"%s\".\n",
|
|
strval);
|
|
goto fail;
|
|
}
|
|
|
|
op->virtual.x = x;
|
|
op->virtual.y = y;
|
|
|
|
break;
|
|
}
|
|
|
|
case USE_DISPLAY_DEVICE_OPTION:
|
|
op->use_display_device =
|
|
disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case CUSTOM_EDID_OPTION:
|
|
op->custom_edid = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case CONNECTED_MONITOR_OPTION:
|
|
op->connected_monitor =
|
|
disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case REGISTRY_DWORDS_OPTION:
|
|
op->registry_dwords = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case COLOR_SPACE_OPTION:
|
|
op->color_space = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case COLOR_RANGE_OPTION:
|
|
op->color_range = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case FLATPANEL_PROPERTIES_OPTION:
|
|
op->flatpanel_properties =
|
|
disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case NVIDIA_3DVISION_USB_PATH_OPTION:
|
|
op->nvidia_3dvision_usb_path = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case NVIDIA_3DVISIONPRO_CONFIG_FILE_OPTION:
|
|
op->nvidia_3dvisionpro_config_file = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case NVIDIA_3DVISION_DISPLAY_TYPE_OPTION:
|
|
|
|
/* mark as disabled, so we can remove the option later */
|
|
|
|
if (disable) {
|
|
op->nvidia_3dvision_display_type = -2;
|
|
break;
|
|
}
|
|
|
|
if (intval < 0 || intval > 2) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid 3D Vision display type option: %d.\n", intval);
|
|
fprintf(stderr, "\n");
|
|
goto fail;
|
|
}
|
|
op->nvidia_3dvision_display_type = intval;
|
|
break;
|
|
|
|
case RESTORE_ORIGINAL_BACKUP_OPTION:
|
|
op->restore_original_backup = TRUE;
|
|
break;
|
|
|
|
case NUM_X_SCREENS_OPTION:
|
|
|
|
if (intval < 1) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid number of X screens: %d.\n", intval);
|
|
fprintf(stderr, "\n");
|
|
goto fail;
|
|
}
|
|
|
|
/* Enable separate X screens */
|
|
set_boolean_option(op,
|
|
XCONFIG_BOOL_VAL(SEPARATE_X_SCREENS_BOOL_OPTION) -
|
|
XCONFIG_BOOL_OPTION_START, TRUE);
|
|
|
|
op->num_x_screens = intval;
|
|
break;
|
|
|
|
case FORCE_COMPOSITION_PIPELINE_OPTION:
|
|
op->force_composition_pipeline =
|
|
disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case FORCE_FULL_COMPOSITION_PIPELINE_OPTION:
|
|
op->force_full_composition_pipeline =
|
|
disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
case ALLOW_HMD_OPTION:
|
|
op->allow_hmd = disable ? NV_DISABLE_STRING_OPTION : strval;
|
|
break;
|
|
|
|
default:
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
/* do tilde expansion on the filenames given */
|
|
|
|
op->xconfig = tilde_expansion(op->xconfig);
|
|
op->output_xconfig = tilde_expansion(op->output_xconfig);
|
|
|
|
return;
|
|
|
|
fail:
|
|
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Invalid commandline, please run `%s --help` "
|
|
"for usage information.\n", argv[0]);
|
|
fprintf(stderr, "\n");
|
|
exit(1);
|
|
|
|
} /* parse_commandline() */
|
|
|
|
|
|
|
|
/*
|
|
* load_default_options - malloc an Options structure
|
|
* and initialize it with default values.
|
|
*
|
|
*/
|
|
|
|
static Options *load_default_options(void)
|
|
{
|
|
Options *op;
|
|
|
|
op = (Options *) nvalloc(sizeof(Options));
|
|
if (!op) return NULL;
|
|
|
|
op->depth = 24;
|
|
op->transparent_index = -1;
|
|
op->stereo = -1;
|
|
op->cool_bits = -1;
|
|
op->nvidia_3dvision_display_type = -1;
|
|
op->tv_over_scan = -1.0;
|
|
op->num_x_screens = -1;
|
|
|
|
xconfigGenerateLoadDefaultOptions(&op->gop);
|
|
|
|
/*
|
|
* XXX save the option structure so that printing routines can
|
|
* access it (and so that we don't have to carry the op everywhere
|
|
* just so that we can pass it to printing routines).
|
|
*/
|
|
{
|
|
extern Options *__op;
|
|
|
|
__op = op;
|
|
}
|
|
|
|
return op;
|
|
|
|
} /* load_default_options() */
|
|
|
|
|
|
|
|
/*
|
|
* backup_file() - create a backup of orig_filename, naming the backup
|
|
* file "<orig_filename>.<suffix>".
|
|
*
|
|
* XXX If we fail to write to the backup file (eg, it is in a
|
|
* read-only directory), then we should do something intelligent like
|
|
* write the backup to the user's home directory.
|
|
*/
|
|
|
|
static int backup_file(Options *op, const char *orig_filename,
|
|
const char *suffix)
|
|
{
|
|
char *filename;
|
|
int ret = FALSE;
|
|
|
|
/* construct the backup filename */
|
|
|
|
filename = nvstrcat(orig_filename, suffix, NULL);
|
|
|
|
/* if the backup file already exists, remove it */
|
|
|
|
if (access(filename, F_OK) == 0) {
|
|
if (unlink(filename) != 0) {
|
|
nv_error_msg("Unable to create backup file '%s' (%s)",
|
|
filename, strerror(errno));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* copy the file */
|
|
|
|
if (!copy_file(orig_filename, filename, 0644)) {
|
|
/* copy_file() prints out its own error messages */
|
|
goto done;
|
|
}
|
|
|
|
nv_info_msg(NULL, "Backed up file '%s' as '%s'", orig_filename, filename);
|
|
ret = TRUE;
|
|
|
|
done:
|
|
|
|
free(filename);
|
|
|
|
return ret;
|
|
|
|
} /* backup_file() */
|
|
|
|
|
|
|
|
/*
|
|
* find_xconfig() - search for an X config file.
|
|
*
|
|
* We search for the filename is this order:
|
|
*
|
|
* 1) "--output-xconfig" option
|
|
*
|
|
* 2) config->filename
|
|
*
|
|
* 3) use xf86openConfigFile()
|
|
*/
|
|
|
|
static char *find_xconfig(Options *op, XConfigPtr config)
|
|
{
|
|
char *filename = NULL;
|
|
|
|
/* 1) "--output-xconfig" option */
|
|
|
|
if (op->output_xconfig) {
|
|
filename = nvstrdup(op->output_xconfig);
|
|
}
|
|
|
|
/* config->filename */
|
|
|
|
if (!filename && config && config->filename) {
|
|
filename = nvstrdup(config->filename);
|
|
}
|
|
|
|
/* use xf86openConfigFile() */
|
|
|
|
if (!filename) {
|
|
const char *f;
|
|
f = xconfigOpenConfigFile(NULL, op->gop.x_project_root);
|
|
if (f) {
|
|
/* dup the string since closing the config file will free
|
|
the string */
|
|
filename = nvstrdup(f);
|
|
xconfigCloseConfigFile();
|
|
}
|
|
}
|
|
|
|
if (!filename) {
|
|
filename = nvstrdup("/etc/X11/xorg.conf");
|
|
}
|
|
|
|
return filename;
|
|
} /* find_xconfig() */
|
|
|
|
|
|
/*
|
|
* restore_backup - search for a backup file with the given suffix;
|
|
* if one is found, restore it.
|
|
*/
|
|
static int restore_backup(Options *op, XConfigPtr config, const char *suffix)
|
|
{
|
|
char *filename = find_xconfig(op, config);
|
|
char *backup = nvstrcat(filename, suffix, NULL);
|
|
struct stat st;
|
|
int ret = FALSE;
|
|
|
|
if (lstat(backup, &st) != 0) {
|
|
nv_error_msg("Unable to restore from original backup file '%s' (%s)",
|
|
backup, strerror(errno));
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* do not restore files if the permissions might allow a malicious user to
|
|
* modify the backup, potentially tricking an administrator into restoring
|
|
* the modified backup.
|
|
*/
|
|
if (!S_ISREG(st.st_mode) /* non-regular files */ ||
|
|
st.st_uid != 0 /* not owned by root*/ ||
|
|
(st.st_gid != 0 && (st.st_mode & S_IWGRP)) /* non-root group write */ ||
|
|
(st.st_mode & S_IWOTH) /* world writable */ ) {
|
|
nv_error_msg("The permissions of the original backup file '%s' are too "
|
|
"loose to be trusted. The file will not be restored.", backup);
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* if the backup is empty, assume that no original x config file existed
|
|
* and delete the current X config file.
|
|
*/
|
|
|
|
if (st.st_size == 0) {
|
|
if (unlink(filename) != 0) {
|
|
nv_error_msg("Unable to remove file '%s' (%s)",
|
|
filename, strerror(errno));
|
|
goto done;
|
|
}
|
|
} else {
|
|
/* copy the file */
|
|
|
|
if (!copy_file(backup, filename, 0644)) {
|
|
/* copy_file() prints out its own error messages */
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* remove backup: a new one is created if nvidia-xconfig is run again */
|
|
|
|
if (access(backup, F_OK) == 0) {
|
|
if (unlink(backup) != 0) {
|
|
nv_error_msg("Unable to remove backup file '%s' (%s)",
|
|
backup, strerror(errno));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (st.st_size == 0) {
|
|
nv_info_msg(NULL, "The backup file '%s' was empty. This usually means "
|
|
"that nvidia-xconfig did not find an X configuration "
|
|
"file the first time it was run. The X configuration "
|
|
"file '%s' was deleted.",
|
|
backup, filename);
|
|
} else {
|
|
nv_info_msg(NULL, "Restored backup file '%s' to '%s'", backup, filename);
|
|
}
|
|
|
|
ret = TRUE;
|
|
|
|
done:
|
|
|
|
free(backup);
|
|
free(filename);
|
|
|
|
return ret;
|
|
} /* restore_backup() */
|
|
|
|
|
|
|
|
/*
|
|
* write_xconfig() - write the Xconfig to file.
|
|
*/
|
|
|
|
static int write_xconfig(Options *op, XConfigPtr config, int first_touch)
|
|
{
|
|
char *filename = find_xconfig(op, config);
|
|
char *d, *tmp = NULL;
|
|
int ret = FALSE;
|
|
|
|
/*
|
|
* XXX it's strange that lack of permission to write to the target
|
|
* location (the likely case with users not having write
|
|
* permission on /etc/X11/ will fail at backup time, rather than
|
|
* when we try to write the new file. Perhaps we should backup to
|
|
* a temporary location where we know we will have write access,
|
|
* try to do the write, and only if we succeed in the write, move
|
|
* the backup file into place.
|
|
*/
|
|
|
|
/* check that we can write to this location */
|
|
|
|
tmp = nvstrdup(filename);
|
|
d = dirname(tmp);
|
|
if (access(d, W_OK) != 0) {
|
|
nv_error_msg("Unable to write to directory '%s'.", d);
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* if the file already exists, create a backup first. if this is our first
|
|
* time writing the x config, create a separate "original" backup file.
|
|
*/
|
|
|
|
if (access(filename, F_OK) == 0) {
|
|
if (first_touch && !backup_file(op, filename, ORIG_SUFFIX)) goto done;
|
|
if (!backup_file(op, filename, BACKUP_SUFFIX)) goto done;
|
|
}
|
|
|
|
/*
|
|
* if no file exists, and this is our first time writing the x config, back
|
|
* up an empty file to use as the "original" backup.
|
|
*/
|
|
|
|
else if (first_touch) {
|
|
char *fakeorig = nvstrcat(filename, ORIG_SUFFIX, NULL);
|
|
if (!copy_file("/dev/null", fakeorig, 0644)) {
|
|
nv_warning_msg("Unable to write an empty backup file \"%s\".",
|
|
fakeorig);
|
|
}
|
|
free(fakeorig);
|
|
}
|
|
|
|
/* write the config file */
|
|
|
|
if (!xconfigWriteConfigFile(filename, config)) {
|
|
nv_error_msg("Unable to write file \"%s\"; please use the "
|
|
"\"--output-xconfig\" commandline option to specify "
|
|
"an alternative output file.", filename);
|
|
goto done;
|
|
}
|
|
|
|
nv_info_msg(NULL, "New X configuration file written to '%s'", filename);
|
|
nv_info_msg(NULL, "");
|
|
|
|
|
|
/* Set the default depth in the Solaris Management Facility
|
|
* to the default depth of the first screen
|
|
*/
|
|
if (op->disable_scf == FALSE) {
|
|
if (!update_scf_depth(config->screens[0].defaultdepth)) {
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
ret = TRUE;
|
|
|
|
done:
|
|
|
|
if (filename) free(filename);
|
|
if (tmp) free(tmp);
|
|
|
|
return ret;
|
|
|
|
} /* write_xconfig() */
|
|
|
|
|
|
|
|
/*
|
|
* find_banner_prefix() - helper for update_banner(); like
|
|
* 'strstr("# nvidia-xconfig:")' but allows arbitrary whitespace between
|
|
* '#' and 'n'.
|
|
*/
|
|
|
|
static char *find_banner_prefix(char *str)
|
|
{
|
|
char *s, *comment = NULL;
|
|
|
|
for (s = str; s && *s; s++) {
|
|
char c = *s;
|
|
|
|
/*
|
|
* if we aren't presently looking at a comment, and we found the
|
|
* start of a comment, then save it and goto the next char
|
|
*/
|
|
|
|
if ((!comment) && (c == '#')) {
|
|
comment = s;
|
|
continue;
|
|
}
|
|
|
|
if (comment) {
|
|
/* ignore space within the comment */
|
|
if (isspace(c)) {
|
|
continue;
|
|
}
|
|
/* if the prefix matches, then return the start of the comment */
|
|
if (strncmp(s, "nvidia-xconfig:", 15) == 0) {
|
|
return comment;
|
|
}
|
|
}
|
|
|
|
/* anything else forces us out of any current comment */
|
|
comment = NULL;
|
|
}
|
|
return NULL;
|
|
|
|
} /* find_banner_prefix() */
|
|
|
|
|
|
|
|
/*
|
|
* update_banner() - add our banner at the top of the config, but
|
|
* first we need to remove any lines that already include our prefix
|
|
* (because presumably they are a banner from an earlier run of
|
|
* nvidia-xconfig)
|
|
*/
|
|
|
|
static void update_banner(XConfigPtr config)
|
|
{
|
|
static const char *banner =
|
|
"X configuration file generated by nvidia-xconfig\n";
|
|
static const char *prefix =
|
|
"# nvidia-xconfig: ";
|
|
|
|
char *s = config->comment;
|
|
char *line, *eol, *tmp;
|
|
|
|
/* remove all lines that begin with the prefix */
|
|
|
|
while (s && (line = find_banner_prefix(s))) {
|
|
|
|
eol = strchr(line, '\n'); /* find the end of the line */
|
|
|
|
if (eol) {
|
|
eol++;
|
|
if (*eol == '\0') eol = NULL;
|
|
}
|
|
|
|
if (line == s) { /* the line with the prefix is at the start */
|
|
if (eol) { /* there is more after the prefix line */
|
|
tmp = strdup(eol);
|
|
free(s);
|
|
s = tmp;
|
|
} else { /* the prefix line is the only line */
|
|
free(s);
|
|
s = NULL;
|
|
}
|
|
} else { /* prefix line is in the middle or end */
|
|
*line = '\0';
|
|
tmp = nvstrcat(s, eol, NULL);
|
|
free(s);
|
|
s = tmp;
|
|
}
|
|
}
|
|
|
|
/* add our prefix lines at the start of the comment */
|
|
|
|
config->comment = nvstrcat(prefix, banner, "# " NV_ID_STRING "\n", s, NULL);
|
|
|
|
if (s) free(s);
|
|
|
|
} /* update_banner() */
|
|
|
|
|
|
|
|
/*
|
|
* find_system_xconfig() - find the system X config file and parse it;
|
|
* returns XConfigPtr if successful, otherwise returns NULL.
|
|
*/
|
|
|
|
static XConfigPtr find_system_xconfig(Options *op)
|
|
{
|
|
const char *filename;
|
|
XConfigPtr config;
|
|
XConfigError error;
|
|
|
|
/* Find and open the existing X config file */
|
|
|
|
filename = xconfigOpenConfigFile(op->xconfig, op->gop.x_project_root);
|
|
|
|
if (filename) {
|
|
nv_info_msg(NULL, "");
|
|
nv_info_msg(NULL, "Using X configuration file: \"%s\".", filename);
|
|
} else {
|
|
nv_warning_msg("Unable to locate/open X configuration file.");
|
|
return NULL;
|
|
}
|
|
|
|
/* Read the opened X config file */
|
|
|
|
error = xconfigReadConfigFile(&config);
|
|
if (error != XCONFIG_RETURN_SUCCESS) {
|
|
xconfigCloseConfigFile();
|
|
return NULL;;
|
|
}
|
|
|
|
/* Close the X config file */
|
|
|
|
xconfigCloseConfigFile();
|
|
|
|
/* Sanitize the X config file */
|
|
|
|
if (!xconfigSanitizeConfig(config, op->screen, &(op->gop))) {
|
|
xconfigFreeConfig(&config);
|
|
return NULL;
|
|
}
|
|
|
|
return config;
|
|
|
|
} /* find_system_xconfig() */
|
|
|
|
|
|
|
|
/*
|
|
* apply_enable_prime_settings() - if the ENABLE PRIME boolean option is
|
|
* enabled, add the required xconfig additions.
|
|
* returns a success/fail boolean.
|
|
*/
|
|
|
|
static int apply_enable_prime_settings(Options *op, XConfigPtr config,
|
|
XConfigLayoutPtr layout)
|
|
{
|
|
DevicesPtr pDevices;
|
|
|
|
if (GET_BOOL_OPTION(op->boolean_option_values, ENABLE_PRIME_OPTION)) {
|
|
/* Add an inactive device for the integrated graphics */
|
|
pDevices = find_devices(op);
|
|
if (!pDevices) {
|
|
nv_error_msg("Unable to find any GPUs in the system.");
|
|
return FALSE;
|
|
}
|
|
xconfigAddInactiveDevice(config, layout, pDevices->nDevices);
|
|
|
|
nv_info_msg(NULL, "X Configuration file set up for PRIME. Please run "
|
|
"\"xrandr --setprovideroutputsource modesetting "
|
|
"NVIDIA-0\" and \"xrandr --auto\" to enable. "
|
|
"See the README for more details.");
|
|
}
|
|
return TRUE;
|
|
} /* apply_enable_prime_settings() */
|
|
|
|
/*
|
|
* apply_enable_external_gpu_option() - if the ENABLE EXTERNAL GPU boolean
|
|
* option is enabled, add the AllowExternalGpus option to the ServerLayout
|
|
* section
|
|
* returns a success/fail boolean
|
|
*/
|
|
|
|
static int apply_enable_external_gpu_option(Options *op, XConfigPtr config,
|
|
XConfigLayoutPtr layout)
|
|
{
|
|
int egpu = GET_BOOL_OPTION(op->boolean_option_values,
|
|
ENABLE_EXTERNAL_GPU_BOOL_OPTION);
|
|
|
|
if (GET_BOOL_OPTION(op->boolean_options, ENABLE_EXTERNAL_GPU_BOOL_OPTION)) {
|
|
xconfigAddNewOption(&(layout->options),
|
|
"AllowExternalGpus",
|
|
(egpu ? "1" : "0"));
|
|
|
|
if (egpu) {
|
|
nv_info_msg(NULL, "X configuration file set up to allow detection "
|
|
"of External GPUs. If the eGPU does not work, "
|
|
"you may need to authorize the associated "
|
|
"Thunderbolt device.\n"
|
|
"Warning: System may become unstable if the "
|
|
"eGPU is hot-unplugged while X is running.\n"
|
|
"See \"Configuring External and Removable "
|
|
"GPUs\" in the README for more details.");
|
|
}
|
|
}
|
|
return TRUE;
|
|
} /* apply_enable_external_gpu_option */
|
|
|
|
|
|
static int update_xconfig(Options *op, XConfigPtr config)
|
|
{
|
|
XConfigLayoutPtr layout;
|
|
XConfigAdjacencyPtr adj;
|
|
int updated;
|
|
|
|
/* get the layout to update */
|
|
|
|
layout = get_layout(op, config);
|
|
if (!layout) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* apply multi-display options */
|
|
|
|
if (!apply_multi_screen_options(op, config, layout)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* apply PRIME settings */
|
|
|
|
if (!apply_enable_prime_settings(op, config, layout)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* apply eGPU setting */
|
|
if (!apply_enable_external_gpu_option(op, config, layout)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* update the device and option for all screens, or the screen
|
|
* or device that was requested.
|
|
*/
|
|
updated = FALSE;
|
|
|
|
for (adj = layout->adjacencies; adj; adj = adj->next) {
|
|
|
|
if (!adj->screen) {
|
|
continue;
|
|
}
|
|
|
|
/* if screen option set: skip adj if not the requested screen */
|
|
|
|
if ((op->screen) &&
|
|
(xconfigNameCompare(op->screen, adj->screen->identifier) != 0)) {
|
|
continue;
|
|
}
|
|
|
|
/* if device option set: skip adj if not the requested device */
|
|
|
|
if ((op->device) &&
|
|
(xconfigNameCompare(op->device, adj->screen->device_name) != 0)) {
|
|
continue;
|
|
}
|
|
|
|
update_screen(op, config, adj->screen);
|
|
updated = TRUE;
|
|
}
|
|
|
|
if (op->screen && !updated) {
|
|
nv_error_msg("Unable to find screen '%s'", op->screen);
|
|
return FALSE;
|
|
}
|
|
|
|
if (op->device && !updated) {
|
|
nv_error_msg("Unable to find device '%s'", op->device);
|
|
return FALSE;
|
|
}
|
|
|
|
update_extensions(op, config);
|
|
|
|
update_modules(config);
|
|
|
|
update_server_flags(op, config);
|
|
|
|
update_banner(config);
|
|
|
|
return TRUE;
|
|
|
|
} /* update_xconfig() */
|
|
|
|
|
|
|
|
/*
|
|
* main program entry point
|
|
*
|
|
* The intended behavior is that, by default, nvidia-xconfig make the
|
|
* system's X config file usable by the NVIDIA X driver. If
|
|
* nvidia-xconfig cannot file the system's X config file, then it
|
|
* attempts to create one and make that usable.
|
|
*
|
|
*
|
|
*/
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
Options *op;
|
|
int ret;
|
|
XConfigPtr config = NULL;
|
|
int first_touch = 0;
|
|
|
|
/* Load defaults */
|
|
|
|
op = load_default_options();
|
|
if (!op) {
|
|
fprintf(stderr, "\nOut of memory error.\n\n");
|
|
return 1;
|
|
}
|
|
|
|
/* parse the commandline */
|
|
|
|
parse_commandline(op, argc, argv);
|
|
|
|
/*
|
|
* first, check for any of special options that cause us to exit
|
|
* early
|
|
*/
|
|
|
|
if (op->keyboard_list) {
|
|
nv_info_msg(NULL, "\nPossible keyboard types; the short name is what "
|
|
"should be passed to the \"--keyboard\" option.\n\n");
|
|
xconfigGeneratePrintPossibleKeyboards();
|
|
return 0;
|
|
}
|
|
|
|
if (op->mouse_list) {
|
|
nv_info_msg(NULL, "\nPossible mouse types; the short name is what should "
|
|
"be passed to the \"--mouse\" option.\n\n");
|
|
xconfigGeneratePrintPossibleMice();
|
|
return 0;
|
|
}
|
|
|
|
if (op->query_gpu_info) {
|
|
ret = query_gpu_info(op);
|
|
return (ret ? 0 : 1);
|
|
}
|
|
|
|
if (op->extract_edids_from_file) {
|
|
ret = extract_edids(op);
|
|
return (ret ? 0 : 1);
|
|
}
|
|
|
|
if (op->restore_original_backup) {
|
|
config = find_system_xconfig(op);
|
|
xconfigGetXServerInUse(&op->gop);
|
|
ret = restore_backup(op, config, ORIG_SUFFIX);
|
|
return (ret ? 0 : 1);
|
|
}
|
|
|
|
/*
|
|
* we want to open and parse the system's existing X config file,
|
|
* if possible
|
|
*/
|
|
|
|
if (!op->force_generate) {
|
|
config = find_system_xconfig(op);
|
|
}
|
|
|
|
/*
|
|
* pass the system config (if any) to the tree printer
|
|
*/
|
|
|
|
if (op->tree) {
|
|
ret = print_tree(op, config);
|
|
return (ret ? 0 : 1);
|
|
}
|
|
|
|
/*
|
|
* Get which X server is in use: Xorg or XFree86
|
|
*/
|
|
xconfigGetXServerInUse(&op->gop);
|
|
|
|
/*
|
|
* if we failed to find the system's config file, generate a new
|
|
* one
|
|
*/
|
|
|
|
if (!config) {
|
|
config = xconfigGenerate(&op->gop);
|
|
first_touch = 1;
|
|
}
|
|
|
|
/*
|
|
* if we don't have a valid config by now, something catestrophic
|
|
* happened
|
|
*/
|
|
|
|
if (!config) {
|
|
nv_error_msg("Unable to generate a usable X configuration file.");
|
|
return 1;
|
|
}
|
|
|
|
/* if a config file existed, check to see if it had an nvidia-xconfig
|
|
* banner: this would suggest that we've touched this file before.
|
|
*/
|
|
|
|
if (!first_touch) {
|
|
first_touch = (find_banner_prefix(config->comment) == NULL);
|
|
}
|
|
|
|
/* now, we have a good config; apply whatever the user requested */
|
|
|
|
update_xconfig(op, config);
|
|
|
|
/* print the config in tree format, if requested */
|
|
|
|
if (op->post_tree) {
|
|
ret = print_tree(op, config);
|
|
return (ret ? 0 : 1);
|
|
}
|
|
|
|
/* write the config back out to file */
|
|
|
|
if (!write_xconfig(op, config, first_touch)) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* main() */
|