static void apply_psu_entry_token(char *token, char *value, void *data) { PSUEntryPtr pPSUEntry = (PSUEntryPtr) data; if (!strcasecmp("current", token)) { pPSUEntry->psu_current = atoi(value); } else if (!strcasecmp("power", token)) { if (!strcasecmp("unknown", value)) { pPSUEntry->psu_power = -1; } else { pPSUEntry->psu_power = atoi(value); } } else if (!strcasecmp("voltage", token)) { if (!strcasecmp("unknown", value)) { pPSUEntry->psu_voltage = -1; } else { pPSUEntry->psu_voltage = atoi(value); } } else if (!strcasecmp("state", token)) { if (!strcasecmp("normal", value)) { pPSUEntry->psu_state = VCS_PSU_STATE_NORMAL; } else { pPSUEntry->psu_state = VCS_PSU_STATE_ABNORMAL; } } else { nv_warning_msg("Unknown PSU Entry token value pair: %s=%s", token, value); } }
static void apply_thermal_entry_token(char *token, char *value, void *data) { ThermalEntryPtr pThermalEntry = (ThermalEntryPtr) data; if (!strcasecmp("intake", token)) { pThermalEntry->intake_temp = atoi(value); } else if (!strcasecmp("exhaust", token)) { pThermalEntry->exhaust_temp = atoi(value); } else if (!strcasecmp("board", token)) { pThermalEntry->board_temp = atoi(value); } else { nv_warning_msg("Unknown Thermal Entry token value pair: %s=%s", token, value); } }
static void apply_fan_entry_token(char *token, char *value, void *data) { FanEntryPtr pFanEntry = (FanEntryPtr) data; if (!strcasecmp("fan", token)) { pFanEntry->fan_number = atoi(value); } else if (!strcasecmp("speed", token)) { pFanEntry->fan_speed = atoi(value); } else if (!strcasecmp("fail", token)) { pFanEntry->fan_failed = atoi(value); } else { nv_warning_msg("Unknown Fan Entry token value pair: %s=%s", token, value); } }
static gboolean ctk_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { XEvent event; CtkEventSource *event_source = (CtkEventSource *) source; CtkEventStruct event_struct; memset(&event_struct, 0, sizeof(event_struct)); /* * if ctk_event_dispatch() is called, then either * ctk_event_prepare() or ctk_event_check() returned TRUE, so we * know there is an event pending */ XNextEvent(event_source->dpy, &event); /* * Handle the ATTRIBUTE_CHANGED_EVENT NV-CONTROL event */ if (event_source->event_base != -1 && (event.type == (event_source->event_base + ATTRIBUTE_CHANGED_EVENT))) { XNVCtrlAttributeChangedEvent *nvctrlevent = (XNVCtrlAttributeChangedEvent *) &event; /* make sure the attribute is in our signal array */ if ((nvctrlevent->attribute <= NV_CTRL_LAST_ATTRIBUTE) && (signals[nvctrlevent->attribute] != 0)) { event_struct.attribute = nvctrlevent->attribute; event_struct.value = nvctrlevent->value; event_struct.display_mask = nvctrlevent->display_mask; /* * XXX Is emitting a signal with g_signal_emit() really * the "correct" way of dispatching the event? */ CTK_EVENT_BROADCAST(event_source, signals[nvctrlevent->attribute], &event_struct, NV_CTRL_TARGET_TYPE_X_SCREEN, nvctrlevent->screen); } /* * Handle the TARGET_ATTRIBUTE_CHANGED_EVENT NV-CONTROL event */ } else if (event_source->event_base != -1 && (event.type == (event_source->event_base +TARGET_ATTRIBUTE_CHANGED_EVENT))) { XNVCtrlAttributeChangedEventTarget *nvctrlevent = (XNVCtrlAttributeChangedEventTarget *) &event; /* make sure the attribute is in our signal array */ if ((nvctrlevent->attribute <= NV_CTRL_LAST_ATTRIBUTE) && (signals[nvctrlevent->attribute] != 0)) { event_struct.attribute = nvctrlevent->attribute; event_struct.value = nvctrlevent->value; event_struct.display_mask = nvctrlevent->display_mask; /* * XXX Is emitting a signal with g_signal_emit() really * the "correct" way of dispatching the event? */ CTK_EVENT_BROADCAST(event_source, signals[nvctrlevent->attribute], &event_struct, nvctrlevent->target_type, nvctrlevent->target_id); } /* * Handle the TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT * NV-CONTROL event. */ } else if (event_source->event_base != -1 && (event.type == (event_source->event_base + TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT))) { XNVCtrlAttributeChangedEventTargetAvailability *nvctrlevent = (XNVCtrlAttributeChangedEventTargetAvailability *) &event; /* make sure the attribute is in our signal array */ if ((nvctrlevent->attribute <= NV_CTRL_LAST_ATTRIBUTE) && (signals[nvctrlevent->attribute] != 0)) { event_struct.attribute = nvctrlevent->attribute; event_struct.value = nvctrlevent->value; event_struct.display_mask = nvctrlevent->display_mask; event_struct.is_availability_changed = TRUE; event_struct.availability = nvctrlevent->availability; /* * XXX Is emitting a signal with g_signal_emit() really * the "correct" way of dispatching the event? */ CTK_EVENT_BROADCAST(event_source, signals[nvctrlevent->attribute], &event_struct, nvctrlevent->target_type, nvctrlevent->target_id); } /* * Handle the TARGET_STRING_ATTRIBUTE_CHANGED_EVENT * NV-CONTROL event. */ } else if (event_source->event_base != -1 && (event.type == (event_source->event_base + TARGET_STRING_ATTRIBUTE_CHANGED_EVENT))) { XNVCtrlStringAttributeChangedEventTarget *nvctrlevent = (XNVCtrlStringAttributeChangedEventTarget *) &event; /* make sure the attribute is in our signal array */ if ((nvctrlevent->attribute <= NV_CTRL_STRING_LAST_ATTRIBUTE) && (string_signals[nvctrlevent->attribute] != 0)) { event_struct.attribute = nvctrlevent->attribute; event_struct.value = 0; event_struct.display_mask = nvctrlevent->display_mask; /* * XXX Is emitting a signal with g_signal_emit() really * the "correct" way of dispatching the event */ CTK_EVENT_BROADCAST(event_source, string_signals[nvctrlevent->attribute], &event_struct, nvctrlevent->target_type, nvctrlevent->target_id); } /* * Handle the TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT * NV-CONTROL event. */ } else if (event_source->event_base != -1 && (event.type == (event_source->event_base + TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT))) { XNVCtrlBinaryAttributeChangedEventTarget *nvctrlevent = (XNVCtrlBinaryAttributeChangedEventTarget *) &event; /* make sure the attribute is in our signal array */ if ((nvctrlevent->attribute <= NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE) && (binary_signals[nvctrlevent->attribute] != 0)) { event_struct.attribute = nvctrlevent->attribute; event_struct.value = 0; event_struct.display_mask = nvctrlevent->display_mask; /* * XXX Is emitting a signal with g_signal_emit() really * the "correct" way of dispatching the event */ CTK_EVENT_BROADCAST(event_source, binary_signals[nvctrlevent->attribute], &event_struct, nvctrlevent->target_type, nvctrlevent->target_id); } /* * Also handle XRandR events. */ } else if (event_source->randr_event_base != -1 && (event.type == (event_source->randr_event_base + RRScreenChangeNotify))) { XRRScreenChangeNotifyEvent *xrandrevent = (XRRScreenChangeNotifyEvent *)&event; int screen; /* Find the screen the window belongs to */ screen = get_screen_of_root(xrandrevent->display, xrandrevent->root); if (screen >= 0) { CTK_EVENT_BROADCAST(event_source, signal_RRScreenChangeNotify, &event, NV_CTRL_TARGET_TYPE_X_SCREEN, screen); } /* * Trap events that get registered but are not handled * properly. */ } else { nv_warning_msg("Unknown event type %d.", event.type); } return TRUE; } /* ctk_event_dispatch() */
NvCtrlXvAttributes * NvCtrlInitXvAttributes(NvCtrlAttributePrivateHandle *h) { NvCtrlXvAttributes *xv = NULL; XvAdaptorInfo *ainfo; unsigned int req, event_base, error_base, nadaptors; int ret, i; const char *error_str = NULL; const char *warn_str = NULL; /* Check parameters */ if ( !h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN ) { goto fail; } /* Open libXv.so.1 */ if ( !open_libxv() ) { warn_str = "Failed to open libXv.so.1: this library " "is not present in your system or is not in your " "LD_LIBRARY_PATH."; goto fail; } /* Allocate the attributes structure */ xv = calloc(1, sizeof(NvCtrlXvAttributes)); if ( xv == NULL ) { error_str = "Out of memory."; goto fail; } /* Verify server support of Xv extension */ ret = __libXv->XvQueryExtension(h->dpy, &(xv->major_version), &(xv->minor_version), &req, &event_base, &error_base); if (ret != Success) goto fail; /* XXX do we have a minimum Xv version? */ /* Get the list of adaptors */ ret = __libXv->XvQueryAdaptors(h->dpy, RootWindow(h->dpy, h->target_id), &nadaptors, &ainfo); if (ret != Success || !nadaptors || !ainfo) goto fail; for (i = 0; i < nadaptors; i++) { if ((strcmp(ainfo[i].name, "NV17 Video Overlay") == 0) || (strcmp(ainfo[i].name, "NV10 Video Overlay") == 0)) { NvCtrlXvOverlayAttributes *attrs; attrs = malloc(sizeof(NvCtrlXvOverlayAttributes)); if ( !attrs ) { error_str = "Out of memory."; goto fail; } attrs->port = ainfo[i].base_id; attrs->saturation = getXvAttribute(h, attrs->port, "XV_SATURATION"); attrs->contrast = getXvAttribute(h, attrs->port, "XV_CONTRAST"); attrs->brightness = getXvAttribute(h, attrs->port, "XV_BRIGHTNESS"); attrs->hue = getXvAttribute(h, attrs->port, "XV_HUE"); attrs->defaults = getXvAttribute(h, attrs->port, "XV_SET_DEFAULTS"); if (!attrs->saturation || !attrs->contrast || !attrs->brightness || !attrs->hue || !attrs->defaults) { if (attrs->saturation) free(attrs->saturation); if (attrs->contrast) free(attrs->contrast); if (attrs->brightness) free(attrs->brightness); if (attrs->hue) free(attrs->hue); if (attrs->defaults) free(attrs->defaults); free(attrs); attrs = NULL; } else { xv->overlay = attrs; } } if (strcmp(ainfo[i].name, "NV17 Video Texture") == 0) { NvCtrlXvTextureAttributes *attrs; attrs = malloc(sizeof(NvCtrlXvTextureAttributes)); if ( !attrs ) { error_str = "Out of memory."; goto fail; } attrs->port = ainfo[i].base_id; attrs->sync_to_vblank = getXvAttribute(h, attrs->port, "XV_SYNC_TO_VBLANK"); attrs->contrast = getXvAttribute(h, attrs->port, "XV_CONTRAST"); attrs->brightness = getXvAttribute(h, attrs->port, "XV_BRIGHTNESS"); attrs->saturation = getXvAttribute(h, attrs->port, "XV_SATURATION"); attrs->hue = getXvAttribute(h, attrs->port, "XV_HUE"); attrs->defaults = getXvAttribute(h, attrs->port, "XV_SET_DEFAULTS"); if (!attrs->sync_to_vblank || !attrs->defaults) { if (attrs->sync_to_vblank) free(attrs->sync_to_vblank); if (attrs->defaults) free(attrs->defaults); free(attrs); attrs = NULL; } else { xv->texture = attrs; } } if (strcmp(ainfo[i].name, "NV05 Video Blitter") == 0) { NvCtrlXvBlitterAttributes *attrs; attrs = malloc(sizeof(NvCtrlXvBlitterAttributes)); if ( !attrs ) { error_str = "Out of memory."; goto fail; } attrs->port = ainfo[i].base_id; attrs->sync_to_vblank = getXvAttribute(h, attrs->port, "XV_SYNC_TO_VBLANK"); attrs->defaults = getXvAttribute(h, attrs->port, "XV_SET_DEFAULTS"); if (!attrs->sync_to_vblank || !attrs->defaults) { if (attrs->sync_to_vblank) free(attrs->sync_to_vblank); if (attrs->defaults) free(attrs->defaults); free(attrs); attrs = NULL; } else { xv->blitter = attrs; } } } return xv; /* Handle failures */ fail: if (error_str) { nv_error_msg("libXv setup error: %s\n", error_str); } if (warn_str) { nv_warning_msg("libXv setup warning: %s\n", warn_str); } if (xv != NULL) { if (xv->overlay) { free(xv->overlay); } if (xv->texture) { free(xv->texture); } if (xv->blitter) { free(xv->blitter); } free(xv); } return NULL; } /* NvCtrlInitXvAttributes() */
static int parse_config_property(const char *file, const char *line, ConfigProperties *conf) { char *no_spaces, *s; char *locale; ConfigPropertiesTableEntry *t; char *timer, *token; TimerConfigProperty *c = NULL; int interval; int ret = NV_FALSE; unsigned int flag; no_spaces = remove_spaces(line); if (!no_spaces) goto done; s = strchr(no_spaces, '='); if (!s) goto done; *s = '\0'; if (nv_strcasecmp(no_spaces, "RcFileLocale")) { locale = ++s; if (setlocale(LC_NUMERIC, locale) == NULL) { nv_warning_msg("Error parsing configuration file '%s': could " "not set the specified locale '%s'.", file, locale); } } else if (nv_strcasecmp(no_spaces, "Timer")) { timer = ++s; token = strtok(timer, ","); if (!token) goto done; c = malloc(sizeof(TimerConfigProperty)); if (!c) { nv_warning_msg("Error parsing configuration file '%s': could " "not allocate memory for timer '%s'.", file, timer); ret = NV_TRUE; goto done; } c->description = replace_characters(token, '_', ' '); if (!c->description) { nv_warning_msg("Error parsing configuration file '%s': could " "not allocate memory for timer '%s'.", file, timer); ret = NV_TRUE; goto done; } token = strtok(NULL, ","); if (!token) goto done; if (nv_strcasecmp(token, "Yes")) { c->user_enabled = 1; } else if (nv_strcasecmp(token, "No")) { c->user_enabled = 0; } else { goto done; } token = strtok(NULL, ","); if (!token) goto done; parse_read_integer(token, &interval); c->interval = interval; c->next = conf->timers; conf->timers = c; } else { for (t = configPropertyTable, flag = 0; t->name; t++) { if (nv_strcasecmp(no_spaces, t->name)) { flag = t->flag; break; } } if (!flag) goto done; s++; if (nv_strcasecmp(s, "yes")) { conf->booleans |= flag; } else if (nv_strcasecmp(s, "no")) { conf->booleans &= ~flag; } else { goto done; } } ret = NV_TRUE; done: if ((ret != NV_TRUE) && c) { if (c->description) free(c->description); free(c); } if (no_spaces) free(no_spaces); return ret; } /* parse_config_property() */
int nv_write_config_file(const char *filename, CtrlHandles *h, ParsedAttribute *p, ConfigProperties *conf) { int screen, ret, entry, bit, val; FILE *stream; time_t now; AttributeTableEntry *a; ReturnStatus status; NVCTRLAttributeValidValuesRec valid; uint32 mask; CtrlHandleTarget *t; char *tmp_d_str, *prefix, scratch[4]; const char *tmp; char *locale = "C"; if (!filename) { nv_error_msg("Unable to open configuration file for writing."); return NV_FALSE; } stream = fopen(filename, "w"); if (!stream) { nv_error_msg("Unable to open file '%s' for writing.", filename); return NV_FALSE; } /* write header */ now = time(NULL); fprintf(stream, "#\n"); fprintf(stream, "# %s\n", filename); fprintf(stream, "#\n"); fprintf(stream, "# Configuration file for nvidia-settings - the NVIDIA " "X Server Settings utility\n"); /* NOTE: ctime(3) generates a new line */ fprintf(stream, "# Generated on %s", ctime(&now)); fprintf(stream, "#\n"); /* * set the locale to "C" before writing the configuration file to * reduce the risk of locale related parsing problems. Restore * the original locale before exiting this function. */ if (setlocale(LC_NUMERIC, "C") == NULL) { nv_warning_msg("Error writing configuration file '%s': could " "not set the locale 'C'.", filename); locale = conf->locale; } /* write the values in ConfigProperties */ write_config_properties(stream, conf, locale); /* for each screen, query each attribute in the table */ fprintf(stream, "\n"); fprintf(stream, "# Attributes:\n"); fprintf(stream, "\n"); /* * Note: we only save writable attributes addressable by X screen * (i.e., we don't look at other target types, yet). */ for (screen = 0; screen < h->targets[X_SCREEN_TARGET].n; screen++) { t = &h->targets[X_SCREEN_TARGET].t[screen]; /* skip it if we don't have a handle for this screen */ if (!t->h) continue; /* * construct the prefix that will be printed in the config * file infront of each attribute on this screen; this will * either be "[screen]" or "[displayname]". */ if (conf->booleans & CONFIG_PROPERTIES_INCLUDE_DISPLAY_NAME_IN_CONFIG_FILE) { prefix = t->name; } else { snprintf(scratch, 4, "%d", screen); prefix = scratch; } /* loop over all the entries in the table */ for (entry = 0; attributeTable[entry].name; entry++) { a = &attributeTable[entry]; /* * skip all attributes that are not supposed to be written * to the config file */ if (a->flags & NV_PARSER_TYPE_NO_CONFIG_WRITE) continue; /* * special case the color attributes because we want to * print floats */ if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) { float c[3], b[3], g[3]; status = NvCtrlGetColorAttributes(t->h, c, b, g); if (status != NvCtrlSuccess) continue; fprintf(stream, "%s%c%s=%f\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, get_color_value(a->attr, c, b, g)); continue; } for (bit = 0; bit < 24; bit++) { mask = 1 << bit; /* * if this bit is not present in the screens's enabled * display device mask (and the X screen has enabled * display devices), skip to the next bit */ if (((t->d & mask) == 0x0) && (t->d)) continue; status = NvCtrlGetValidDisplayAttributeValues (t->h, mask, a->attr, &valid); if (status != NvCtrlSuccess) goto exit_bit_loop; if ((valid.permissions & ATTRIBUTE_TYPE_WRITE) == 0x0) goto exit_bit_loop; status = NvCtrlGetDisplayAttribute(t->h, mask, a->attr, &val); if (status != NvCtrlSuccess) goto exit_bit_loop; if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) { tmp_d_str = display_device_mask_to_display_device_name(mask); fprintf(stream, "%s%c%s[%s]=%d\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, tmp_d_str, val); free(tmp_d_str); continue; } else { fprintf(stream, "%s%c%s=%d\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, val); /* fall through to exit_bit_loop */ } exit_bit_loop: bit = 25; /* XXX force us out of the display device loop */ } /* bit */ } /* entry */ } /* screen */ /* * loop the ParsedAttribute list, writing the attributes to file. * note that we ignore conf->include_display_name_in_config_file * when writing these parsed attributes; this is because parsed * attributes (like the framelock properties) require a display * name be specified (since there are multiple X servers * involved). */ while (p) { char target_str[64]; if (!p->next) { p = p->next; continue; } tmp = nv_get_attribute_name(p->attr, NV_PARSER_TYPE_STRING_ATTRIBUTE, p->flags); if (!tmp) { nv_error_msg("Failure to save unknown attribute %d.", p->attr); p = p->next; continue; } /* * if the parsed attribute has a target specification, and a * target type other than an X screen, include a target * specification in what we write to the .rc file. */ target_str[0] = '\0'; if ((p->flags & NV_PARSER_HAS_TARGET) && (p->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN)) { int j; /* Find the target name of the target type */ for (j = 0; targetTypeTable[j].name; j++) { if (targetTypeTable[j].nvctrl == p->target_type) { snprintf(target_str, 64, "[%s:%d]", targetTypeTable[j].parsed_name, p->target_id); break; } } } if (p->display_device_mask) { tmp_d_str = display_device_mask_to_display_device_name (p->display_device_mask); fprintf(stream, "%s%s%c%s[%s]=%d\n", p->display, target_str, DISPLAY_NAME_SEPARATOR, tmp, tmp_d_str, p->val); free(tmp_d_str); } else { fprintf(stream, "%s%s%c%s=%d\n", p->display, target_str, DISPLAY_NAME_SEPARATOR, tmp, p->val); } p = p->next; } setlocale(LC_NUMERIC, conf->locale); /* close the configuration file */ ret = fclose(stream); if (ret != 0) { nv_error_msg("Failure while closing file '%s'.", filename); return NV_FALSE; } return NV_TRUE; } /* nv_write_config_file() */
int nv_read_config_file(const char *file, const char *display_name, ParsedAttribute *p, ConfigProperties *conf) { int fd, ret, length; struct stat stat_buf; char *buf, *locale; ParsedAttributeWrapper *w = NULL; if (!file) { /* * file is NULL, likely because tilde_expansion() failed and * returned NULL; silently fail */ return NV_FALSE; } /* open the file */ fd = open(file, O_RDONLY); if (fd == -1) { /* * It's OK if the file doesn't exist... but should we print a * warning? */ return NV_FALSE; } /* get the size of the file */ ret = fstat(fd, &stat_buf); if (ret == -1) { nv_error_msg("Unable to determine size of file '%s' (%s).", file, strerror(errno)); return NV_FALSE; } if (stat_buf.st_size == 0) { nv_warning_msg("File '%s' has zero size; not reading.", file); close(fd); return NV_TRUE; } length = stat_buf.st_size; /* map the file into memory */ buf = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0); if (buf == (void *) -1) { nv_error_msg("Unable to mmap file '%s' for reading (%s).", file, strerror(errno)); return NV_FALSE; } /* * save the current locale, parse the actual text in the file * and restore the saved locale (could be changed). */ locale = strdup(conf->locale); w = parse_config_file(buf, file, length, conf); setlocale(LC_NUMERIC, locale); free(locale); /* unmap and close the file */ if (munmap (buf, stat_buf.st_size) == -1) { nv_error_msg("Unable to unmap file '%s' after reading (%s).", file, strerror(errno)); return NV_FALSE; } close(fd); if (!w) return NV_FALSE; /* process the parsed attributes */ ret = process_config_file_attributes(file, w, display_name); /* * add any relevant parsed attributes back to the list to be * passed to the gui */ save_gui_parsed_attributes(w, p); if (w) free(w); return ret; } /* nv_read_config_file() */
int nv_write_config_file(const char *filename, const CtrlSystem *system, const ParsedAttribute *p, const ConfigProperties *conf) { int ret, entry, val, randr_gamma_available; FILE *stream; time_t now; ReturnStatus status; CtrlAttributePerms perms; CtrlTargetNode *node; CtrlTarget *t; char *prefix, scratch[4]; char *locale = "C"; if (!filename) { nv_error_msg("Unable to open configuration file for writing."); return NV_FALSE; } stream = fopen(filename, "w"); if (!stream) { nv_error_msg("Unable to open file '%s' for writing.", filename); return NV_FALSE; } /* write header */ now = time(NULL); fprintf(stream, "#\n"); fprintf(stream, "# %s\n", filename); fprintf(stream, "#\n"); fprintf(stream, "# Configuration file for nvidia-settings - the NVIDIA " "X Server Settings utility\n"); /* NOTE: ctime(3) generates a new line */ fprintf(stream, "# Generated on %s", ctime(&now)); fprintf(stream, "#\n"); /* * set the locale to "C" before writing the configuration file to * reduce the risk of locale related parsing problems. Restore * the original locale before exiting this function. */ if (setlocale(LC_NUMERIC, "C") == NULL) { nv_warning_msg("Error writing configuration file '%s': could " "not set the locale 'C'.", filename); locale = conf->locale; } /* write the values in ConfigProperties */ write_config_properties(stream, conf, locale); /* for each screen, query each attribute in the table */ fprintf(stream, "\n"); fprintf(stream, "# Attributes:\n"); fprintf(stream, "\n"); /* * Note: we only save writable attributes addressable by X screen here * followed by attributes for display target types. */ for (node = system->targets[X_SCREEN_TARGET]; node; node = node->next) { t = node->t; /* skip it if we don't have a handle for this screen */ if (!t->h) continue; /* * construct the prefix that will be printed in the config * file in front of each attribute on this screen; this will * either be "[screen]" or "[displayname]". */ if (conf->booleans & CONFIG_PROPERTIES_INCLUDE_DISPLAY_NAME_IN_CONFIG_FILE) { prefix = t->name; } else { snprintf(scratch, 4, "%d", NvCtrlGetTargetId(t)); prefix = scratch; } /* loop over all the entries in the table */ for (entry = 0; entry < attributeTableLen; entry++) { const AttributeTableEntry *a = &attributeTable[entry]; /* * skip all attributes that are not supposed to be written * to the config file */ if (a->flags.no_config_write) { continue; } /* * special case the color attributes because we want to * print floats */ if (a->type == CTRL_ATTRIBUTE_TYPE_COLOR) { float c[3], b[3], g[3]; /* * if we are using RandR gamma, skip saving the color info */ status = NvCtrlGetAttribute(t, NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE, &val); if (status == NvCtrlSuccess && val) continue; status = NvCtrlGetColorAttributes(t, c, b, g); if (status != NvCtrlSuccess) continue; fprintf(stream, "%s%c%s=%f\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, get_color_value(a->attr, c, b, g)); continue; } /* Only write out integer attributes, string and SDI CSC attributes * aren't written here. */ if (a->type != CTRL_ATTRIBUTE_TYPE_INTEGER) { continue; } /* * Ignore display attributes (they are written later on) and only * write attributes that can be written for an X screen target */ status = NvCtrlGetAttributePerms(t, a->type, a->attr, &perms); if (status != NvCtrlSuccess || !(perms.write) || !(perms.valid_targets & CTRL_TARGET_PERM_BIT(X_SCREEN_TARGET)) || (perms.valid_targets & CTRL_TARGET_PERM_BIT(DISPLAY_TARGET))) { continue; } status = NvCtrlGetAttribute(t, a->attr, &val); if (status != NvCtrlSuccess) { continue; } if (a->f.int_flags.is_display_id) { const char *name = NvCtrlGetDisplayConfigName(system, val); if (name) { fprintf(stream, "%s%c%s=%s\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, name); } continue; } fprintf(stream, "%s%c%s=%d\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, val); } /* entry */ } /* screen */ /* * Write attributes addressable to display targets */ for (node = system->targets[DISPLAY_TARGET]; node; node = node->next) { t = node->t; /* skip it if we don't have a handle for this display */ if (!t->h) continue; /* * check to see if we have RANDR gamma available. We may * skip writing attributes if it is missing. */ status = NvCtrlGetAttribute(t, NV_CTRL_ATTR_RANDR_GAMMA_AVAILABLE, &randr_gamma_available); if (status != NvCtrlSuccess) { randr_gamma_available = 0; } /* Get the prefix we want to use for the display device target */ prefix = create_display_device_target_string(t, conf); /* loop over all the entries in the table */ for (entry = 0; entry < attributeTableLen; entry++) { const AttributeTableEntry *a = &attributeTable[entry]; /* * skip all attributes that are not supposed to be written * to the config file */ if (a->flags.no_config_write) { continue; } /* * for the display target we only write color attributes for now */ if (a->type == CTRL_ATTRIBUTE_TYPE_COLOR) { float c[3], b[3], g[3]; if (!randr_gamma_available) continue; status = NvCtrlGetColorAttributes(t, c, b, g); if (status != NvCtrlSuccess) continue; fprintf(stream, "%s%c%s=%f\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, get_color_value(a->attr, c, b, g)); continue; } /* Only write out integer attributes, string and SDI CSC attributes * aren't written here. */ if (a->type != CTRL_ATTRIBUTE_TYPE_INTEGER) { continue; } /* Make sure this is a display and writable attribute */ status = NvCtrlGetAttributePerms(t, a->type, a->attr, &perms); if (status != NvCtrlSuccess || !(perms.write) || !(perms.valid_targets & CTRL_TARGET_PERM_BIT(DISPLAY_TARGET))) { continue; } status = NvCtrlGetAttribute(t, a->attr, &val); if (status == NvCtrlSuccess) { fprintf(stream, "%s%c%s=%d\n", prefix, DISPLAY_NAME_SEPARATOR, a->name, val); } } free(prefix); } /* * loop the ParsedAttribute list, writing the attributes to file. * note that we ignore conf->include_display_name_in_config_file * when writing these parsed attributes; this is because parsed * attributes (like the framelock properties) require a display * name be specified (since there are multiple X servers * involved). */ while (p) { char target_str[64]; const AttributeTableEntry *a = p->attr_entry; if (!p->next) { p = p->next; continue; } /* * if the parsed attribute has a target specification, and a * target type other than an X screen, include a target * specification in what we write to the .rc file. */ target_str[0] = '\0'; if (p->parser_flags.has_target && (p->target_type != X_SCREEN_TARGET)) { const CtrlTargetTypeInfo *targetTypeInfo; /* Find the target name of the target type */ targetTypeInfo = NvCtrlGetTargetTypeInfo(p->target_type); if (targetTypeInfo) { snprintf(target_str, 64, "[%s:%d]", targetTypeInfo->parsed_name, p->target_id); } } if (a->flags.hijack_display_device) { fprintf(stream, "%s%s%c%s[0x%08x]=%d\n", p->display, target_str, DISPLAY_NAME_SEPARATOR, a->name, p->display_device_mask, p->val.i); } else { fprintf(stream, "%s%s%c%s=%d\n", p->display, target_str, DISPLAY_NAME_SEPARATOR, a->name, p->val.i); } p = p->next; } setlocale(LC_NUMERIC, conf->locale); /* close the configuration file */ ret = fclose(stream); if (ret != 0) { nv_error_msg("Failure while closing file '%s'.", filename); return NV_FALSE; } return NV_TRUE; } /* nv_write_config_file() */
/* * get_screens_to_clone() - try to detect automatically how many heads has each * device in order to use that number to create more than two separate X * screens. If the user specifies the option --num-x-screens <quantity>, that * value is used. If neither the user specifies the quantity or the number of * heads can be detected automatically, it uses 2 heads (the standard * behavior). This function returns an array of size nscreens with the number * of screens to clone per screen candidate. The caller is responsible of * freeing the memory of that array. */ static int* get_screens_to_clone(Options *op, const XConfigScreenPtr *screen_candidates, int nscreens) { DevicesPtr pDevices; int *screens_to_clone, *supported_screens; int i, j, devs_found; screens_to_clone = nvalloc(nscreens * sizeof(int)); supported_screens = nvalloc(nscreens * sizeof(int)); /* Detect the number of supported screens per screen candidate */ devs_found = FALSE; pDevices = find_devices(op); if (pDevices) { for (i = 0; i < nscreens; i++) { int bus, slot, scratch; if (!screen_candidates[i]) { continue; } /* parse the bus id for this candidate screen */ if (!xconfigParsePciBusString(screen_candidates[i]->device->busid, &bus, &slot, &scratch)) { continue; } for (j = 0; j < pDevices->nDevices; j++) { if ((pDevices->devices[j].dev.bus == bus) && (pDevices->devices[j].dev.slot == slot)) { if (pDevices->devices[j].crtcs > 0) { supported_screens[i] = pDevices->devices[j].crtcs; } break; } } } free_devices(pDevices); devs_found = TRUE; } /* If user has defined a number of screens per GPU, use that value */ if (op->num_x_screens > 0) { for (i = 0; i < nscreens; i++) { if (!screen_candidates[i]) { continue; } /* Print error when user specifies more X screens than supported */ if (devs_found && op->num_x_screens > supported_screens[i]) { nv_warning_msg("Number of X screens specified is higher than the " "supported quantity (%d)", supported_screens[i]); } screens_to_clone[i] = op->num_x_screens; } goto done; } for (i = 0; i < nscreens; i++) { if (screen_candidates[i]) { if (devs_found) { /* If devices found, use the supported screens number */ screens_to_clone[i] = supported_screens[i]; } else { /* Default behavior (2 heads per GPU) */ screens_to_clone[i] = 2; } } } done: nvfree(supported_screens); return screens_to_clone; }
DevicesPtr find_devices(Options *op) { DevicesPtr pDevices = NULL; DisplayDevicePtr pDisplayDevice; int i, j, n, count = 0; unsigned int mask, bit; DeviceRec tmpDevice; NvCfgPciDevice *devs = NULL; NvCfgBool is_primary_device; NvCfgBool ret; char *lib_path; void *lib_handle; NvCfgBool (*__getDevices)(int *n, NvCfgDevice **devs); NvCfgBool (*__openDevice)(int bus, int slot, NvCfgDeviceHandle *handle); NvCfgBool (*__getPciDevices)(int *n, NvCfgPciDevice **devs); NvCfgBool (*__openPciDevice)(int domain, int bus, int slot, int function, NvCfgDeviceHandle *handle); NvCfgBool (*__getNumCRTCs)(NvCfgDeviceHandle handle, int *crtcs); NvCfgBool (*__getProductName)(NvCfgDeviceHandle handle, char **name); NvCfgBool (*__getDisplayDevices)(NvCfgDeviceHandle handle, unsigned int *display_device_mask); NvCfgBool (*__getEDID)(NvCfgDeviceHandle handle, unsigned int display_device, NvCfgDisplayDeviceInformation *info); NvCfgBool (*__isPrimaryDevice)(NvCfgDeviceHandle handle, NvCfgBool *is_primary_device); NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle); NvCfgBool (*__getDeviceUUID)(NvCfgDeviceHandle handle, char **uuid); /* dlopen() the nvidia-cfg library */ #define __LIB_NAME "libnvidia-cfg.so.1" if (op->nvidia_cfg_path) { lib_path = nvstrcat(op->nvidia_cfg_path, "/", __LIB_NAME, NULL); } else { lib_path = strdup(__LIB_NAME); } lib_handle = dlopen(lib_path, RTLD_NOW); nvfree(lib_path); if (!lib_handle) { nv_warning_msg("error opening %s: %s.", __LIB_NAME, dlerror()); return NULL; } #define __GET_FUNC(proc, name) \ (proc) = dlsym(lib_handle, (name)); \ if (!(proc)) { \ nv_warning_msg("error retrieving symbol %s from %s: %s", \ (name), __LIB_NAME, dlerror()); \ dlclose(lib_handle); \ return NULL; \ } /* required functions */ __GET_FUNC(__getDevices, "nvCfgGetDevices"); __GET_FUNC(__openDevice, "nvCfgOpenDevice"); __GET_FUNC(__getPciDevices, "nvCfgGetPciDevices"); __GET_FUNC(__openPciDevice, "nvCfgOpenPciDevice"); __GET_FUNC(__getNumCRTCs, "nvCfgGetNumCRTCs"); __GET_FUNC(__getProductName, "nvCfgGetProductName"); __GET_FUNC(__getDisplayDevices, "nvCfgGetDisplayDevices"); __GET_FUNC(__getEDID, "nvCfgGetEDID"); __GET_FUNC(__closeDevice, "nvCfgCloseDevice"); __GET_FUNC(__getDeviceUUID, "nvCfgGetDeviceUUID"); /* optional functions */ __isPrimaryDevice = dlsym(lib_handle, "nvCfgIsPrimaryDevice"); if (__getPciDevices(&count, &devs) != NVCFG_TRUE) { return NULL; } if (count == 0) return NULL; pDevices = nvalloc(sizeof(DevicesRec)); pDevices->devices = nvalloc(sizeof(DeviceRec) * count); pDevices->nDevices = count; for (i = 0; i < count; i++) { pDevices->devices[i].dev = devs[i]; if (__openPciDevice(devs[i].domain, devs[i].bus, devs[i].slot, 0, &(pDevices->devices[i].handle)) != NVCFG_TRUE) { goto fail; } if (__getNumCRTCs(pDevices->devices[i].handle, &pDevices->devices[i].crtcs) != NVCFG_TRUE) { goto fail; } if (__getProductName(pDevices->devices[i].handle, &pDevices->devices[i].name) != NVCFG_TRUE) { /* This call may fail with little impact to the Device section */ pDevices->devices[i].name = NULL; } if (__getDeviceUUID(pDevices->devices[i].handle, &pDevices->devices[i].uuid) != NVCFG_TRUE) { goto fail; } if (__getDisplayDevices(pDevices->devices[i].handle, &mask) != NVCFG_TRUE) { goto fail; } pDevices->devices[i].displayDeviceMask = mask; /* count the number of display devices */ for (n = j = 0; j < 32; j++) { if (mask & (1 << j)) n++; } pDevices->devices[i].nDisplayDevices = n; if (n) { /* allocate the info array of the right size */ pDevices->devices[i].displayDevices = nvalloc(sizeof(DisplayDeviceRec) * n); /* fill in the info array */ for (n = j = 0; j < 32; j++) { bit = 1 << j; if (!(bit & mask)) continue; pDisplayDevice = &pDevices->devices[i].displayDevices[n]; pDisplayDevice->mask = bit; if (__getEDID(pDevices->devices[i].handle, bit, &pDisplayDevice->info) != NVCFG_TRUE) { pDisplayDevice->info_valid = FALSE; } else { pDisplayDevice->info_valid = TRUE; } n++; } } else { pDevices->devices[i].displayDevices = NULL; } if ((i != 0) && (__isPrimaryDevice != NULL) && (__isPrimaryDevice(pDevices->devices[i].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)); } ret = __closeDevice(pDevices->devices[i].handle); pDevices->devices[i].handle = NULL; if (ret != NVCFG_TRUE) { goto fail; } } goto done; fail: nv_warning_msg("Unable to use the nvidia-cfg library to query NVIDIA " "hardware."); for (i = 0; i < pDevices->nDevices; i++) { /* close the opened device */ if (pDevices->devices[i].handle) { __closeDevice(pDevices->devices[i].handle); } } free_devices(pDevices); pDevices = NULL; /* fall through */ done: if (devs) free(devs); return pDevices; } /* find_devices() */
/* * Rebuilds the list of display devices available for syncing. */ static void xv_sync_to_display_rebuild_buttons(CtkXVideo *ctk_xvideo, gboolean update_status) { ReturnStatus ret; int enabled_display_id; int *pData; int len; int i; GtkWidget *last_button; GtkWidget *button; CtrlTarget *ctrl_target = ctk_xvideo->ctrl_target; /* Remove all buttons */ ctk_empty_container(ctk_xvideo->xv_sync_to_display_button_box); /* Rebuild the list based on the curren configuration */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_XV_SYNC_TO_DISPLAY_ID, &enabled_display_id); if (ret != NvCtrlSuccess) { nv_warning_msg("Failed to query XV Sync display ID on X screen %d.", NvCtrlGetTargetId(ctrl_target)); return; } ret = NvCtrlGetBinaryAttribute(ctrl_target, 0, NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN, (unsigned char **)(&pData), &len); if (ret != NvCtrlSuccess) { nv_warning_msg("Failed to query list of displays assigned to X screen " " %d.", NvCtrlGetTargetId(ctrl_target)); return; } /* Add a button for No Display Specified */ last_button = NULL; button = xv_sync_to_display_radio_button_add(ctk_xvideo, NULL, NV_CTRL_XV_SYNC_TO_DISPLAY_ID_AUTO); if (button) { /* Track the first button */ if (!last_button) { ctk_xvideo->xv_sync_to_display_buttons = button; } last_button = button; } /* Add a button for each display device */ for (i = 0; i < pData[0]; i++) { int display_id = pData[1+i]; button = xv_sync_to_display_radio_button_add(ctk_xvideo, last_button, display_id); if (!button) { continue; } /* Make sure the enabled display is marked as so */ if (display_id == enabled_display_id) { xv_sync_to_display_set_enabled(ctk_xvideo, button, update_status); } /* Track the first button */ if (!last_button) { ctk_xvideo->xv_sync_to_display_buttons = button; } last_button = button; } gtk_widget_show_all(ctk_xvideo->xv_sync_to_display_button_box); }
static gboolean update_fan_status(CtkVcs *ctk_object) { gint ret; char *fan_entry_str = NULL; char *tokens; GtkWidget *table; GtkWidget *label; FanEntry current_fan; gchar output_str[16]; gint current_row; if (!ctk_object->fan_status_container) { return FALSE; } ret = NvCtrlGetStringAttribute(ctk_object->handle, NV_CTRL_STRING_VCSC_FAN_STATUS, &fan_entry_str); if (ret != NvCtrlSuccess) { return FALSE; } ctk_empty_container(ctk_object->fan_status_container); /* Generate the new table */ table = gtk_table_new(1, 3, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 3); gtk_table_set_col_spacings(GTK_TABLE(table), 15); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_box_pack_start(GTK_BOX(ctk_object->fan_status_container), table, FALSE, FALSE, 0); label = gtk_label_new("Fan Number"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_widget_set_size_request(label, ctk_object->req.width, -1); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new("Fan Speed"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new("Fan Status"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); /* Parse string of fan entries and populate table */ current_row = 1; for (tokens = strtok(fan_entry_str, ";"); tokens; tokens = strtok(NULL, ";")) { /* Invalidate fan entry */ current_fan.fan_number = -1; current_fan.fan_speed = -1; current_fan.fan_failed = -1; parse_token_value_pairs(tokens, apply_fan_entry_token, ¤t_fan); if ((current_fan.fan_number != -1) && (current_fan.fan_speed != -1) && (current_fan.fan_failed != -1)) { gtk_table_resize(GTK_TABLE(table), current_row + 1, 3); g_snprintf(output_str, 16, "%d", current_fan.fan_number); label = gtk_label_new(output_str); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_widget_set_size_request(label, ctk_object->req.width, -1); gtk_table_attach(GTK_TABLE(table), label, 0, 1, current_row, current_row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); g_snprintf(output_str, 16, "%d rpm", current_fan.fan_speed); label = gtk_label_new(output_str); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 1, 2, current_row, current_row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); if (!current_fan.fan_failed) { g_snprintf(output_str, 16, "Ok"); } else { g_snprintf(output_str, 16, "Failed"); } label = gtk_label_new(output_str); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 2, 3, current_row, current_row + 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); current_row++; } else { nv_warning_msg("Incomplete Fan Entry (fan=%d, speed=%d, failFlag=%d)", current_fan.fan_number, current_fan.fan_speed, current_fan.fan_failed); } } gtk_widget_show_all(table); XFree(fan_entry_str); return TRUE; }