diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:26:53 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:26:53 -0800 |
commit | 776e01ad78bae30842ca1bc5b9e78ab7c143924f (patch) | |
tree | d656daeee6c86a777eb55f301e1ec290d5b13755 | |
parent | aedec718b1d6e9487861528dfb310db0b3a53c89 (diff) |
-rw-r--r-- | XF86Config-parser/Makefile | 3 | ||||
-rw-r--r-- | XF86Config-parser/Merge.c | 712 | ||||
-rw-r--r-- | XF86Config-parser/Monitor.c | 14 | ||||
-rw-r--r-- | XF86Config-parser/xf86Parser.h | 11 | ||||
-rw-r--r-- | extract_edids.c | 1 | ||||
-rw-r--r-- | multiple_screens.c | 18 | ||||
-rw-r--r-- | nvgetopt.c | 11 | ||||
-rw-r--r-- | nvgetopt.h | 13 | ||||
-rw-r--r-- | nvidia-cfg.h | 12 | ||||
-rw-r--r-- | nvidia-xconfig.c | 100 | ||||
-rw-r--r-- | nvidia-xconfig.h | 8 | ||||
-rw-r--r-- | option_table.h | 46 | ||||
-rw-r--r-- | options.c | 42 |
13 files changed, 980 insertions, 11 deletions
diff --git a/XF86Config-parser/Makefile b/XF86Config-parser/Makefile index ef973a6..721945d 100644 --- a/XF86Config-parser/Makefile +++ b/XF86Config-parser/Makefile @@ -17,7 +17,8 @@ SRC = \ Write.c \ Util.c \ Extensions.c \ - Generate.c + Generate.c \ + Merge.c OBJS = $(SRC:%.c=%.o) DEPS = $(SRC:%.c=%.d) diff --git a/XF86Config-parser/Merge.c b/XF86Config-parser/Merge.c new file mode 100644 index 0000000..2931934 --- /dev/null +++ b/XF86Config-parser/Merge.c @@ -0,0 +1,712 @@ +/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ + +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "Configint.h" + + + +/* + * xconfigAddRemovedOptionComment() - Makes a note in the comment + * string "existing_comments" that a particular option has been + * removed. + * + */ +static void xconfigAddRemovedOptionComment(char **existing_comments, + XConfigOptionPtr option) +{ + int len; + char *str; + + if (!option || !existing_comments) + return; + + len = 32 + strlen(xconfigOptionName(option)) + + strlen(xconfigOptionValue(option)); + + str = (char *)malloc(len); + + if (str) { + snprintf(str, len, "# Removed Option \"%s\" \"%s\"", + xconfigOptionName(option), + xconfigOptionValue(option)); + *existing_comments = xconfigAddComment(*existing_comments, str); + } + +} /* xconfigAddRemovedOptionComment() */ + + + +/* + * xconfigRemoveNamedOption() - Removes the named option from an option + * list and (if specified) adds a comment to an existing comments string + * + */ +static void xconfigRemoveNamedOption(XConfigOptionPtr *head, char *name, + char **comments) +{ + XConfigOptionPtr option; + + option = xconfigFindOption(*head, name); + if (option) { + if (comments) { + xconfigAddRemovedOptionComment(comments, option); + } + *head = xconfigRemoveOption(*head, option); + } + +} /* xconfigRemoveNamedOption() */ + + + +/* + * xconfigMergeOption() - Merge option "name" from option source + * list "srcHead" to option destination list "dstHead". + * + * Merging here means: + * + * If the option is not in the source config, remove it from the dest + * config. + * + * If the option is in the source config, make sure the dest config + * contains the option with the same value as the source config. + * + * if "comments" is given, a comment will be added to note when + * an option has been removed/replaced. + * + */ +static void xconfigMergeOption(XConfigOptionPtr *dstHead, + XConfigOptionPtr *srcHead, + const char *name, char **comments) +{ + XConfigOptionPtr srcOption = xconfigFindOption(*srcHead, name); + XConfigOptionPtr dstOption = xconfigFindOption(*dstHead, name); + + if (!srcOption) { + if (dstOption) { + *dstHead = xconfigRemoveOption(*dstHead, dstOption); + } + } else { + if (!dstOption || strcmp(xconfigOptionValue(srcOption), + xconfigOptionValue(dstOption))) { + + if (dstOption && comments) { + xconfigAddRemovedOptionComment(comments, dstOption); + } + *dstHead = xconfigAddNewOption + (*dstHead, xconfigStrdup(name), + xconfigStrdup(xconfigOptionValue(srcOption))); + } + } + +} /* xconfigMergeOption() */ + + + +/* + * xconfigMergeFlags() - Updates the destination's list of server flag + * options with the options found in the source config. + * + * Optons in the destination are either added or updated. Options that + * are found in the destination config and not in the source config are + * not modified. + * + * Returns 1 if the merge was successful and 0 if not. + */ +static int xconfigMergeFlags(XConfigPtr dstConfig, XConfigPtr srcConfig) +{ + if (srcConfig->flags) { + XConfigOptionPtr option; + + /* Flag section was not found, create a new one */ + if (!dstConfig->flags) { + dstConfig->flags = + (XConfigFlagsPtr) calloc(1, sizeof(XConfigFlagsRec)); + if (!dstConfig->flags) return 0; + } + + option = srcConfig->flags->options; + while (option) { + xconfigMergeOption(&(dstConfig->flags->options), + &(srcConfig->flags->options), + xconfigOptionName(option), + &(dstConfig->flags->comment)); + option = option->next; + } + } + + return 1; + +} /* xconfigMergeFlags() */ + + + +/* + * xconfigMergeMonitors() - Updates information in the destination monitor + * with that of the source monitor. + * + */ +static void xconfigMergeMonitors(XConfigMonitorPtr dstMonitor, + XConfigMonitorPtr srcMonitor) +{ + int i; + + + /* Update vendor */ + + free(dstMonitor->vendor); + dstMonitor->vendor = xconfigStrdup(srcMonitor->vendor); + + /* Update modelname */ + + free(dstMonitor->modelname); + dstMonitor->modelname = xconfigStrdup(srcMonitor->modelname); + + /* Update horizontal sync */ + + dstMonitor->n_hsync = srcMonitor->n_hsync; + for (i = 0; i < srcMonitor->n_hsync; i++) { + dstMonitor->hsync[i].lo = srcMonitor->hsync[i].lo; + dstMonitor->hsync[i].hi = srcMonitor->hsync[i].hi; + } + + /* Update vertical sync */ + + dstMonitor->n_vrefresh = srcMonitor->n_vrefresh; + for (i = 0; i < srcMonitor->n_hsync; i++) { + dstMonitor->vrefresh[i].lo = srcMonitor->vrefresh[i].lo; + dstMonitor->vrefresh[i].hi = srcMonitor->vrefresh[i].hi; + } + + /* XXX Remove the destination monitor's "UseModes" references to + * avoid having the wrong modelines tied to the new monitor. + */ + xconfigFreeModesLinkList(dstMonitor->modes_sections); + dstMonitor->modes_sections = NULL; + +} /* xconfigMergeMonitors() */ + + + +/* + * xconfigMergeAllMonitors() - This function ensures that all monitors in + * the source config appear in the destination config by adding and/or + * updating the "appropriate" destination monitor sections. + * + */ +static int xconfigMergeAllMonitors(XConfigPtr dstConfig, XConfigPtr srcConfig) +{ + XConfigMonitorPtr dstMonitor; + XConfigMonitorPtr srcMonitor; + + + /* Make sure all monitors in the src config are also in the dst config */ + + for (srcMonitor = srcConfig->monitors; + srcMonitor; + srcMonitor = srcMonitor->next) { + + dstMonitor = + xconfigFindMonitor(srcMonitor->identifier, dstConfig->monitors); + + /* Monitor section was not found, create a new one and add it */ + if (!dstMonitor) { + dstMonitor = + (XConfigMonitorPtr) calloc(1, sizeof(XConfigMonitorRec)); + if (!dstMonitor) return 0; + + dstMonitor->identifier = xconfigStrdup(srcMonitor->identifier); + + dstConfig->monitors = (XConfigMonitorPtr) + xconfigAddListItem((GenericListPtr)dstConfig->monitors, + (GenericListPtr)dstMonitor); + } + + /* Do the merge */ + xconfigMergeMonitors(dstMonitor, srcMonitor); + } + + return 1; + +} /* xconfigMergeAllMonitors() */ + + + +/* + * xconfigMergeDevices() - Updates information in the destination device + * with that of the source device. + * + */ +static void xconfigMergeDevices(XConfigDevicePtr dstDevice, + XConfigDevicePtr srcDevice) +{ + // XXX Zero out the device section? + + /* Update driver */ + + free(dstDevice->driver); + dstDevice->driver = xconfigStrdup(srcDevice->driver); + + /* Update vendor */ + + free(dstDevice->vendor); + dstDevice->vendor = xconfigStrdup(srcDevice->vendor); + + /* Update bus ID */ + + free(dstDevice->busid); + dstDevice->busid = xconfigStrdup(srcDevice->busid); + + /* Update board */ + + free(dstDevice->board); + dstDevice->board = xconfigStrdup(srcDevice->board); + + /* Update chip info */ + + dstDevice->chipid = srcDevice->chipid; + dstDevice->chiprev = srcDevice->chiprev; + + /* Update IRQ */ + + dstDevice->irq = srcDevice->irq; + + /* Update screen */ + + dstDevice->screen = srcDevice->screen; + +} /* xconfigMergeDevices() */ + + + +/* + * xconfigMergeAllDevices() - This function ensures that all devices in + * the source config appear in the destination config by adding and/or + * updating the "appropriate" destination device sections. + * + */ +static int xconfigMergeAllDevices(XConfigPtr dstConfig, XConfigPtr srcConfig) +{ + XConfigDevicePtr dstDevice; + XConfigDevicePtr srcDevice; + + + /* Make sure all monitors in the src config are also in the dst config */ + + for (srcDevice = srcConfig->devices; + srcDevice; + srcDevice = srcDevice->next) { + + dstDevice = + xconfigFindDevice(srcDevice->identifier, dstConfig->devices); + + /* Device section was not found, create a new one and add it */ + if (!dstDevice) { + dstDevice = + (XConfigDevicePtr) calloc(1, sizeof(XConfigDeviceRec)); + if (!dstDevice) return 0; + + dstDevice->identifier = xconfigStrdup(srcDevice->identifier); + + dstConfig->devices = (XConfigDevicePtr) + xconfigAddListItem((GenericListPtr)dstConfig->devices, + (GenericListPtr)dstDevice); + } + + /* Do the merge */ + xconfigMergeDevices(dstDevice, srcDevice); + } + + return 1; + +} /* xconfigMergeAllDevices() */ + + + +/* + * xconfigMergeDriverOptions() - Update the (Screen) driver options + * of the destination config with information from the source config. + * + * - Assumes the source options are all found in the srcScreen->options. + * - Updates only those options listed in the srcScreen->options. + * + */ +static int xconfigMergeDriverOptions(XConfigScreenPtr dstScreen, + XConfigScreenPtr srcScreen) +{ + XConfigOptionPtr option; + XConfigDisplayPtr display; + + option = srcScreen->options; + while (option) { + char *name = xconfigOptionName(option); + + /* Remove the option from all non-screen option lists */ + + if (dstScreen->device) { + xconfigRemoveNamedOption(&(dstScreen->device->options), name, + &(dstScreen->device->comment)); + } + if (dstScreen->monitor) { + xconfigRemoveNamedOption(&(dstScreen->monitor->options), name, + &(dstScreen->monitor->comment)); + } + for (display = dstScreen->displays; display; display = display->next) { + xconfigRemoveNamedOption(&(display->options), name, + &(display->comment)); + } + + /* Update/Add the option to the screen's option list */ + { + // XXX Only add a comment if the value changed. + XConfigOptionPtr old = + xconfigFindOption(dstScreen->options, name); + + if (!old || !strcmp(xconfigOptionValue(option), + xconfigOptionValue(old))) { + xconfigRemoveNamedOption(&(dstScreen->options), name, + NULL); + } else { + xconfigRemoveNamedOption(&(dstScreen->options), name, + &(dstScreen->comment)); + } + } + + /* Add the option to the screen->options list */ + + dstScreen->options = + xconfigAddNewOption(dstScreen->options, + xconfigStrdup(name), + xconfigStrdup(xconfigOptionValue(option))); + + option = option->next; + } + + return 1; + +} /* xconfigMergeDriverOptions() */ + + + +/* + * xconfigMergeDisplays() - Duplicates display information from the + * source screen to the destination screen. + * + */ +static int xconfigMergeDisplays(XConfigScreenPtr dstScreen, + XConfigScreenPtr srcScreen) +{ + XConfigDisplayPtr dstDisplay; + XConfigDisplayPtr srcDisplay; + XConfigOptionPtr srcOption; + XConfigModePtr srcMode, dstMode, lastDstMode; + + /* Free all the displays in the destination screen */ + + xconfigFreeDisplayList(dstScreen->displays); + + /* Copy all te displays */ + + for (srcDisplay = srcScreen->displays; + srcDisplay; + srcDisplay = srcDisplay->next) { + + /* Create a new display */ + + dstDisplay = xconfigAlloc(sizeof(XConfigDisplayRec)); + if (!dstDisplay) return 0; + + /* Copy display fields */ + + dstDisplay->frameX0 = srcDisplay->frameX0; + dstDisplay->frameY0 = srcDisplay->frameY0; + dstDisplay->virtualX = srcDisplay->virtualX; + dstDisplay->virtualY = srcDisplay->virtualY; + dstDisplay->depth = srcDisplay->depth; + dstDisplay->bpp = srcDisplay->bpp; + dstDisplay->visual = xconfigStrdup(srcDisplay->visual); + dstDisplay->weight = srcDisplay->weight; + dstDisplay->black = srcDisplay->black; + dstDisplay->white = srcDisplay->white; + dstDisplay->comment = xconfigStrdup(srcDisplay->comment); + + /* Copy options over */ + + srcOption = srcDisplay->options; + while (srcOption) { + xconfigMergeOption(&(dstDisplay->options), + &(srcDisplay->options), + xconfigOptionName(srcOption), + NULL); + srcOption = srcOption->next; + } + + /* Copy modes over */ + + lastDstMode = NULL; + srcMode = srcDisplay->modes; + while (srcMode) { + + /* Copy the mode */ + + dstMode = xconfigAddMode(NULL, srcMode->mode_name); + + /* Add mode at the end of the list */ + + if ( !lastDstMode ) { + dstDisplay->modes = dstMode; + } else { + lastDstMode->next = dstMode; + } + lastDstMode = dstMode; + + srcMode = srcMode->next; + } + } + + return 1; + +} /* xconfigMergeDisplays() */ + + + +/* + * xconfigMergeScreens() - Updates information in the destination screen + * with that of the source screen. + * + * NOTE: This assumes the Monitor and Device sections have already been + * merged. + * + */ +static void xconfigMergeScreens(XConfigScreenPtr dstScreen, + XConfigPtr dstConfig, + XConfigScreenPtr srcScreen, + XConfigPtr srcConfig) +{ + /* Use the right device */ + + free(dstScreen->device_name); + dstScreen->device_name = xconfigStrdup(srcScreen->device_name); + dstScreen->device = + xconfigFindDevice(dstScreen->device_name, dstConfig->devices); + + + /* Use the right monitor */ + + free(dstScreen->monitor_name); + dstScreen->monitor_name = xconfigStrdup(srcScreen->monitor_name); + dstScreen->monitor = + xconfigFindMonitor(dstScreen->monitor_name, dstConfig->monitors); + + + /* Update the right default depth */ + + dstScreen->defaultdepth = srcScreen->defaultdepth; + + + /* Copy over the display section */ + + xconfigMergeDisplays(dstScreen, srcScreen); + + + /* Update the screen's driver options */ + + xconfigMergeDriverOptions(dstScreen, srcScreen); + +} /* xconfigMergeScreens() */ + + + +/* + * xconfigMergeAllScreens() - This function ensures that all screens in + * the source config appear in the destination config by adding and/or + * updating the "appropriate" destination screen sections. + * + */ +static int xconfigMergeAllScreens(XConfigPtr dstConfig, XConfigPtr srcConfig) +{ + XConfigScreenPtr srcScreen; + XConfigScreenPtr dstScreen; + + + /* Make sure all src screens are in the dst config */ + + for (srcScreen = srcConfig->screens; + srcScreen; + srcScreen = srcScreen->next) { + + dstScreen = + xconfigFindScreen(srcScreen->identifier, dstConfig->screens); + + /* Screen section was not found, create a new one and add it */ + if (!dstScreen) { + dstScreen = + (XConfigScreenPtr) calloc(1, sizeof(XConfigScreenRec)); + if (!dstScreen) return 0; + + dstScreen->identifier = xconfigStrdup(srcScreen->identifier); + + dstConfig->screens = (XConfigScreenPtr) + xconfigAddListItem((GenericListPtr)dstConfig->screens, + (GenericListPtr)dstScreen); + } + + /* Do the merge */ + xconfigMergeScreens(dstScreen, dstConfig, srcScreen, srcConfig); + } + + return 1; + +} /* xconfigMergeAllScreens() */ + + + +/* + * xconfigMergeLayout() - Updates information in the destination's first + * layout with that of the source's first layout. + * + */ +static int xconfigMergeLayout(XConfigPtr dstConfig, XConfigPtr srcConfig) +{ + XConfigLayoutPtr srcLayout = srcConfig->layouts; + XConfigLayoutPtr dstLayout = dstConfig->layouts; + + XConfigAdjacencyPtr srcAdj; + XConfigAdjacencyPtr dstAdj; + XConfigAdjacencyPtr lastDstAdj; + + /* Clear the destination's adjacency list */ + + xconfigFreeAdjacencyList(dstLayout->adjacencies); + + /* Copy adjacencies over */ + + lastDstAdj = NULL; + srcAdj = srcLayout->adjacencies; + while (srcAdj) { + + /* Copy the adjacency */ + + dstAdj = + (XConfigAdjacencyPtr) calloc(1, sizeof(XConfigAdjacencyRec)); + + dstAdj->scrnum = srcAdj->scrnum; + dstAdj->screen_name = xconfigStrdup(srcAdj->screen_name); + dstAdj->top_name = xconfigStrdup(srcAdj->top_name); + dstAdj->bottom_name = xconfigStrdup(srcAdj->bottom_name); + dstAdj->left_name = xconfigStrdup(srcAdj->left_name); + dstAdj->right_name = xconfigStrdup(srcAdj->right_name); + dstAdj->where = srcAdj->where; + dstAdj->x = srcAdj->x; + dstAdj->y = srcAdj->y; + dstAdj->refscreen = xconfigStrdup(srcAdj->refscreen); + + dstAdj->screen = + xconfigFindScreen(dstAdj->screen_name, dstConfig->screens); + dstAdj->top = + xconfigFindScreen(dstAdj->top_name, dstConfig->screens); + dstAdj->bottom = + xconfigFindScreen(dstAdj->bottom_name, dstConfig->screens); + dstAdj->left = + xconfigFindScreen(dstAdj->left_name, dstConfig->screens); + dstAdj->right = + xconfigFindScreen(dstAdj->right_name, dstConfig->screens); + + /* Add adjacency at the end of the list */ + + if ( !lastDstAdj ) { + dstLayout->adjacencies = dstAdj; + } else { + lastDstAdj->next = dstAdj; + } + lastDstAdj = dstAdj; + + srcAdj = srcAdj->next; + } + + return 1; + +} /* xconfigMergeLayout() */ + + + +/* + * xconfigMergeConfigs() - Merges the source X configuration with the + * destination X configuration. + * + * NOTE: This function is currently only used for merging X config files + * for display configuration reasons. As such, the merge assumes + * that the dst config file is the target config file and that + * mostly, only new display configuration information should be + * copied from the source X config to the destination X config. + * + */ +int xconfigMergeConfigs(XConfigPtr dstConfig, XConfigPtr srcConfig) +{ + /* Make sure the X config is falid */ + // make_xconfig_usable(dstConfig); + + + /* Merge the server flag (Xinerama) section */ + + if (!xconfigMergeFlags(dstConfig, srcConfig)) { + return 0; + } + + + /* Merge the monitor sections */ + + if (!xconfigMergeAllMonitors(dstConfig, srcConfig)) { + return 0; + } + + + /* Merge the device sections */ + + if (!xconfigMergeAllDevices(dstConfig, srcConfig)) { + return 0; + } + + + /* Merge the screen sections */ + + if (!xconfigMergeAllScreens(dstConfig, srcConfig)) { + return 0; + } + + + /* Merge the first layout */ + + if (!xconfigMergeLayout(dstConfig, srcConfig)) { + return 0; + } + + return 1; + +} /* xconfigMergeConfigs() */ diff --git a/XF86Config-parser/Monitor.c b/XF86Config-parser/Monitor.c index cacc284..e8d8e3c 100644 --- a/XF86Config-parser/Monitor.c +++ b/XF86Config-parser/Monitor.c @@ -833,6 +833,20 @@ xconfigFreeModeLineList (XConfigModeLinePtr ptr) } } +void +xconfigFreeModesLinkList (XConfigModesLinkPtr ptr) +{ + XConfigModesLinkPtr prev; + + while (ptr) + { + TEST_FREE (ptr->modes_name); + prev = ptr; + ptr = ptr->next; + free (prev); + } +} + XConfigMonitorPtr xconfigFindMonitor (const char *ident, XConfigMonitorPtr p) { diff --git a/XF86Config-parser/xf86Parser.h b/XF86Config-parser/xf86Parser.h index 40b8162..7013b9b 100644 --- a/XF86Config-parser/xf86Parser.h +++ b/XF86Config-parser/xf86Parser.h @@ -652,6 +652,8 @@ void xconfigFreeVideoPortList(XConfigVideoPortPtr ptr); void xconfigFreeBuffersList (XConfigBuffersPtr ptr); void xconfigFreeDRI(XConfigDRIPtr ptr); void xconfigFreeExtensions(XConfigExtensionsPtr ptr); +void xconfigFreeModesLinkList(XConfigModesLinkPtr ptr); + /* @@ -734,4 +736,13 @@ void xconfigGeneratePrintPossibleKeyboards(void); int xconfigCheckCoreInputDevices(GenerateOptions *gop, XConfigPtr config, XConfigLayoutPtr layout); + +/* + * X config tools + */ + +int xconfigMergeConfigs(XConfigPtr dstConfig, XConfigPtr srcConfig); + + + #endif /* _xf86Parser_h_ */ diff --git a/extract_edids.c b/extract_edids.c index 25a4747..8ae75b2 100644 --- a/extract_edids.c +++ b/extract_edids.c @@ -77,6 +77,7 @@ #include <sys/types.h> #include <pwd.h> #include <stdarg.h> +#include <strings.h> /* bzero() */ #include "nvidia-xconfig.h" diff --git a/multiple_screens.c b/multiple_screens.c index a8f6acb..d57f4c7 100644 --- a/multiple_screens.c +++ b/multiple_screens.c @@ -114,8 +114,10 @@ DevicesPtr find_devices(Options *op) DisplayDevicePtr pDisplayDevice; int i, j, n, count = 0; unsigned int mask, bit; + DeviceRec tmpDevice; NvCfgDeviceHandle handle; NvCfgDevice *devs = NULL; + NvCfgBool is_primary_device; char *lib_path; void *lib_handle; @@ -128,6 +130,8 @@ DevicesPtr find_devices(Options *op) NvCfgBool (*__getEDID)(NvCfgDeviceHandle handle, unsigned int display_device, NvCfgDisplayDeviceInformation *info); + NvCfgBool (*__isPrimaryDevice)(NvCfgDeviceHandle handle, + NvCfgBool *is_primary_device); NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle); /* dlopen() the nvidia-cfg library */ @@ -157,7 +161,8 @@ DevicesPtr find_devices(Options *op) dlclose(lib_handle); \ return NULL; \ } - + + /* required functions */ __GET_FUNC(__getDevices, "nvCfgGetDevices"); __GET_FUNC(__openDevice, "nvCfgOpenDevice"); __GET_FUNC(__getNumCRTCs, "nvCfgGetNumCRTCs"); @@ -165,6 +170,9 @@ DevicesPtr find_devices(Options *op) __GET_FUNC(__getDisplayDevices, "nvCfgGetDisplayDevices"); __GET_FUNC(__getEDID, "nvCfgGetEDID"); __GET_FUNC(__closeDevice, "nvCfgCloseDevice"); + + /* optional functions */ + __isPrimaryDevice = dlsym(lib_handle, "nvCfgIsPrimaryDevice"); if (__getDevices(&count, &devs) != NVCFG_TRUE) { return NULL; @@ -232,6 +240,14 @@ DevicesPtr find_devices(Options *op) pDevices->devices[i].displayDevices = NULL; } + if ((i != 0) && (__isPrimaryDevice != NULL) && + (__isPrimaryDevice(handle, &is_primary_device) == NVCFG_TRUE) && + (is_primary_device == NVCFG_TRUE)) { + memcpy(&tmpDevice, &pDevices->devices[0], sizeof(DeviceRec)); + memcpy(&pDevices->devices[0], &pDevices->devices[i], sizeof(DeviceRec)); + memcpy(&pDevices->devices[i], &tmpDevice, sizeof(DeviceRec)); + } + if (__closeDevice(handle) != NVCFG_TRUE) goto fail; } @@ -49,7 +49,8 @@ */ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, - char **strval, int *boolval, int *intval, int *disable_val) + char **strval, int *boolval, int *intval, double *doubleval, + int *disable_val) { char *c, *a, *arg, *name = NULL, *argument=NULL; int i, found = NVGETOPT_FALSE, ret = 0, val = NVGETOPT_FALSE; @@ -239,6 +240,14 @@ int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, } } else if ((o->flags & NVGETOPT_STRING_ARGUMENT) && (strval)) { *strval = strdup(argument); + } else if ((o->flags & NVGETOPT_DOUBLE_ARGUMENT) && (doubleval)) { + char *endptr; + *doubleval = (double) strtod(argument, &endptr); + if (*endptr) { + fprintf(stderr, "%s: \"%s\" is not a valid argument for " + "option \"%s\".\n", argv[0], argument, arg); + goto done; + } } else { fprintf(stderr, "%s: error while assigning argument for " "option \"%s\".\n", argv[0], arg); @@ -73,9 +73,17 @@ #define NVGETOPT_ALLOW_DISABLE 0x8 +/* + * indicates that the option takes an argument to be interpretted as + * an double; on success, nvgetopt will return the parsed double + * argument through 'doubleval'. + */ + +#define NVGETOPT_DOUBLE_ARGUMENT 0x10 #define NVGETOPT_HAS_ARGUMENT (NVGETOPT_STRING_ARGUMENT | \ - NVGETOPT_INTEGER_ARGUMENT) + NVGETOPT_INTEGER_ARGUMENT | \ + NVGETOPT_DOUBLE_ARGUMENT) typedef struct { const char *name; @@ -86,6 +94,7 @@ typedef struct { } NVGetoptOption; int nvgetopt(int argc, char *argv[], const NVGetoptOption *options, - char **strval, int *boolval, int *intval, int *disable_val); + char **strval, int *boolval, int *intval, double *doubleval, + int *disable_val); #endif /* __NVGETOPT_H__ */ diff --git a/nvidia-cfg.h b/nvidia-cfg.h index 020d947..6069d2a 100644 --- a/nvidia-cfg.h +++ b/nvidia-cfg.h @@ -226,4 +226,16 @@ NvCfgBool nvCfgGetEDID(NvCfgDeviceHandle handle, unsigned int display_device, NvCfgDisplayDeviceInformation *info); + +/* + * nvCfgIsPrimaryDevice() - determines whether the specified NVIDIA + * device is the primary device. On success, NVCFG_TRUE will be + * returned and is_primary_device set to indicate whether the + * device is the primary device. On failure, NVCFG_FALSE will be + * returned. + */ + +NvCfgBool nvCfgIsPrimaryDevice(NvCfgDeviceHandle handle, + NvCfgBool *is_primary_device); + #endif /* __NVIDIA_CFG__ */ diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c index 3ae1af8..be6a4ff 100644 --- a/nvidia-xconfig.c +++ b/nvidia-xconfig.c @@ -236,6 +236,7 @@ Options *parse_commandline(int argc, char *argv[]) int c, boolval; char *strval; int intval, disable; + double doubleval; op = (Options *) nvalloc(sizeof(Options)); @@ -243,11 +244,13 @@ Options *parse_commandline(int argc, char *argv[]) op->nvagp = -1; op->transparent_index = -1; op->stereo = -1; + op->cool_bits = -1; + op->tv_over_scan = -1.0; while (1) { c = nvgetopt(argc, argv, __options, &strval, - &boolval, &intval, &disable); + &boolval, &intval, &doubleval, &disable); if (c == -1) break; @@ -346,6 +349,101 @@ Options *parse_commandline(int argc, char *argv[]) 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 TV_OVER_SCAN_OPTION: + + /* mark as disabled, so we can remove the option later */ + + if (disable) { + op->tv_over_scan = -2.0; + break; + } + + if (doubleval >= 0.0 && doubleval <= 1.0) { + op->tv_over_scan = doubleval; + } else { + fprintf(stderr, "Invalid TVOverScan value: %f.\n", doubleval); + 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 */ diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h index b252b6d..c6084ab 100644 --- a/nvidia-xconfig.h +++ b/nvidia-xconfig.h @@ -88,8 +88,9 @@ typedef struct { #define PROBE_ALL_GPUS_BOOL_OPTION 33 #define DYNAMIC_TWINVIEW_BOOL_OPTION 34 #define INCLUDE_IMPLICIT_METAMODES_BOOL_OPTION 35 +#define USE_EVENTS_BOOL_OPTION 36 -#define XCONFIG_BOOL_OPTION_COUNT (INCLUDE_IMPLICIT_METAMODES_BOOL_OPTION + 1) +#define XCONFIG_BOOL_OPTION_COUNT (USE_EVENTS_BOOL_OPTION + 1) /* # of 32-bit variables needed to hold all the boolean options (bits) */ #define XCONFIG_BOOL_OPTION_SLOTS \ @@ -140,6 +141,7 @@ typedef struct __options { int nvagp; int transparent_index; int stereo; + int cool_bits; char *xconfig; char *output_xconfig; @@ -157,6 +159,10 @@ typedef struct __options { char *twinview_orientation; char *use_display_device; char *custom_edid; + char *tv_standard; + char *tv_out_format; + + double tv_over_scan; struct { int x; diff --git a/option_table.h b/option_table.h index 8b59c03..0b19d10 100644 --- a/option_table.h +++ b/option_table.h @@ -37,6 +37,10 @@ #define VIRTUAL_OPTION 26 #define USE_DISPLAY_DEVICE_OPTION 27 #define CUSTOM_EDID_OPTION 28 +#define TV_STANDARD_OPTION 29 +#define TV_OUT_FORMAT_OPTION 30 +#define TV_OVER_SCAN_OPTION 31 +#define COOL_BITS_OPTION 32 /* * To add a boolean option to nvidia-xconfig: @@ -138,6 +142,13 @@ static const NVGetoptOption __options[] = { NVGETOPT_IS_BOOLEAN, NULL, "Disable or enable the \"NoBandWidthTest\" X configuration option." }, + { "cool-bits", COOL_BITS_OPTION, + NVGETOPT_INTEGER_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL, + "Enable or disable the \"Coolbits\" X configuration option. Setting this " + "option will enable support in the NV-CONTROL X extension for manipulating " + "GPU clock settings. Default value is 0.\n" + "WARNING: this may cause system damage and void warranties." }, + { "composite", XCONFIG_BOOL_VAL(COMPOSITE_BOOL_OPTION), NVGETOPT_IS_BOOLEAN, NULL, "Enable or disable the \"Composite\" X extension." }, @@ -153,8 +164,11 @@ static const NVGetoptOption __options[] = { { "custom-edid", CUSTOM_EDID_OPTION, NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "CUSTOM-EDID", "Enable or disable the \"CustomEDID\" X configuration option; " - "setting this option forces the X driver to use the EDID specified " - "in a file rather than the display's EDID." }, + "setting this option forces the X driver to use the EDID specified." + "This option is a semicolon-separated list of pairs of display device names " + "and filename pairs; e.g \"CRT-0:\\tmp\\edid.bin\". Note that a display " + "device name must always be specified even if only one EDID is" + " specified. " }, { "dac-8bit", XCONFIG_BOOL_VAL(DAC_8BIT_BOOL_OPTION), NVGETOPT_IS_BOOLEAN, NULL, @@ -392,7 +406,7 @@ static const NVGetoptOption __options[] = { "Enable or disable the \"Rotate\" X configuration option. Valid values " "for [ROTATE] are 'normal', 'left', 'CCW', 'inverted', " "'right', and 'CW'. Rotation can be disabled " }, - + { "screen", SCREEN_OPTION, NVGETOPT_STRING_ARGUMENT, NULL, "The nvidia-xconfig utility operates on one or more screens within a " "Server Layout in the X configuration file. If this option is " @@ -425,6 +439,24 @@ static const NVGetoptOption __options[] = { "clone mode stereo), 5 (SeeReal digital flat panel), 6 (Sharp3D " "digital flat panel)." }, + { "tv-standard", TV_STANDARD_OPTION, + NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "TV-STANDARD", + "Enable or disable the \"TVStandard\" X configuration option. Valid " + "values for \"TVStandard\" are: \"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\"." }, + + { "tv-out-format", TV_OUT_FORMAT_OPTION, + NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "TV-OUT-FORMAT", + "Enable or disable the \"TVOutFormat\" X configuration option. Valid " + "values for \"TVOutFormat\" are: \"SVIDEO\" and \"COMPOSITE\"." }, + + { "tv-over-scan", TV_OVER_SCAN_OPTION, + NVGETOPT_DOUBLE_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL, + "Enable or disable the \"TVOverScan\" X configuration option. Valid " + "values are decimal values in the range 1.0 and 0.0." }, + { "twinview", XCONFIG_BOOL_VAL(TWINVIEW_BOOL_OPTION), NVGETOPT_IS_BOOLEAN, NULL, "Enable or disable TwinView." }, @@ -488,6 +520,14 @@ static const NVGetoptOption __options[] = { NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "DISPLAY-DEVICE", "Force the X driver to use the display device specified." }, + { "use-events", + XCONFIG_BOOL_VAL(USE_EVENTS_BOOL_OPTION), NVGETOPT_IS_BOOLEAN, NULL, + "Enable or disable \"UseEvents\" X configuration option. Setting this " + "option will enable the X driver to use the system events in some cases " + "when it is waiting for the hardware. With this option X driver sets an " + "event handler and waits for the hardware through the poll() system " + "call. This option defaults to FALSE." }, + { "virtual", VIRTUAL_OPTION, NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "WIDTHxHEIGHT", "Specify the virtual screen resolution." }, @@ -74,6 +74,7 @@ static const NvidiaXConfigOption __options[] = { { PROBE_ALL_GPUS_BOOL_OPTION, FALSE, "ProbeAllGpus" }, { DYNAMIC_TWINVIEW_BOOL_OPTION, FALSE, "DynamicTwinView" }, { INCLUDE_IMPLICIT_METAMODES_BOOL_OPTION,FALSE, "IncludeImplicitMetaModes" }, + { USE_EVENTS_BOOL_OPTION, FALSE, "UseEvents" }, { 0, FALSE, NULL }, }; @@ -513,6 +514,45 @@ void update_options(Options *op, XConfigScreenPtr screen) set_option_value(screen, "CustomEDID", op->custom_edid); } } - + /* add the TVStandard option */ + + if (op->tv_standard) { + remove_option(screen, "TVStandard"); + if (op->tv_standard != NV_DISABLE_STRING_OPTION) { + set_option_value(screen, "TVStandard", op->tv_standard); + } + } + + /* add the TVOutFormat option */ + + if (op->tv_out_format) { + remove_option(screen, "TVOutFormat"); + if (op->tv_out_format != NV_DISABLE_STRING_OPTION) { + set_option_value(screen, "TVOutFormat", op->tv_out_format); + } + } + + /* add the TVOverScan option */ + + if (op->tv_over_scan != -1.0) { + remove_option(screen, "TVOverScan"); + if (op->tv_over_scan != -2.0) { + snprintf(scratch, 8, "%f", op->tv_over_scan); + set_option_value(screen, "TVOverScan", scratch); + } + } + + /* add the Coolbits option */ + + if (op->cool_bits != -1) { + remove_option(screen, "Coolbits"); + if (op->cool_bits != -2) { + snprintf(scratch, 8, "%d", op->cool_bits); + set_option_value(screen, "Coolbits", scratch); + } + } + + + } /* update_options() */ |