/* ctk_event_emit_string() - Emits signal(s) on a registered ctk_event object. * This function is primarily used to simulate NV-CONTROL events such * that various parts of nvidia-settings can communicate (internally) */ void ctk_event_emit_string(CtkEvent *ctk_event, unsigned int mask, int attrib) { CtkEventStruct event; CtkEventSource *source; Display *dpy = NvCtrlGetDisplayPtr(ctk_event->handle); if (attrib > NV_CTRL_STRING_LAST_ATTRIBUTE) return; /* Find the event source */ source = event_sources; while (source) { if (source->dpy == dpy) { break; } source = source->next; } if (!source) return; /* Broadcast event to all relevant ctk_event objects */ event.attribute = attrib; event.value = 0; event.display_mask = mask; CTK_EVENT_BROADCAST(source, string_signals[attrib], &event, NvCtrlGetTargetType(ctk_event->handle), NvCtrlGetTargetId(ctk_event->handle)); } /* ctk_event_emit_string() */
/* ctk_event_emit() - Emits signal(s) on a registered ctk_event object. * This function is primarily used to simulate NV-CONTROL events such * that various parts of nvidia-settings can communicate (internally) */ void ctk_event_emit(CtkEvent *ctk_event, unsigned int mask, int attrib, int value) { CtrlEvent event; CtkEventSource *source; CtrlTarget *ctrl_target = ctk_event->ctrl_target; NvCtrlEventHandle *event_handle = NvCtrlGetEventHandle(ctrl_target); if (attrib > NV_CTRL_LAST_ATTRIBUTE) return; /* Find the event source */ source = event_sources; while (source) { if (source->event_handle == event_handle) { break; } source = source->next; } if (!source) return; /* Broadcast event to all relevant ctk_event objects */ memset(&event, 0, sizeof(CtrlEvent)); event.type = CTRL_EVENT_TYPE_INTEGER_ATTRIBUTE; event.target_type = NvCtrlGetTargetType(ctrl_target); event.target_id = NvCtrlGetTargetId(ctrl_target); event.int_attr.attribute = attrib; event.int_attr.value = value; CTK_EVENT_BROADCAST(source, signals[attrib], &event); } /* ctk_event_emit() */
GtkWidget* ctk_ecc_new(CtrlTarget *ctrl_target, CtkConfig *ctk_config, CtkEvent *ctk_event) { GObject *object; CtkEcc *ctk_ecc; GtkWidget *hbox, *hbox2, *vbox, *hsep, *hseparator, *table; GtkWidget *banner, *label, *eventbox; int64_t sbit_error; int64_t aggregate_sbit_error; int64_t dbit_error; int64_t aggregate_dbit_error; gint ecc_config_supported; gint val, row = 0; gboolean sbit_error_available; gboolean aggregate_sbit_error_available; gboolean dbit_error_available; gboolean aggregate_dbit_error_available; gboolean ecc_enabled; gboolean ecc_default_status; ReturnStatus ret; gchar *ecc_enabled_string; gchar *str = NULL; /* make sure we have a handle */ g_return_val_if_fail((ctrl_target != NULL) && (ctrl_target->h != NULL), NULL); /* * check if ECC support available. */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_SUPPORTED, &val); if (ret != NvCtrlSuccess || val != NV_CTRL_GPU_ECC_SUPPORTED_TRUE) { return NULL; } /* create the CtkEcc object */ object = g_object_new(CTK_TYPE_ECC, NULL); ctk_ecc = CTK_ECC(object); ctk_ecc->ctrl_target = ctrl_target; ctk_ecc->ctk_config = ctk_config; ctk_ecc->ecc_toggle_warning_dlg_shown = FALSE; sbit_error_available = TRUE; dbit_error_available = TRUE; aggregate_sbit_error_available = TRUE; aggregate_dbit_error_available = TRUE; sbit_error = 0; dbit_error = 0; aggregate_sbit_error = 0; aggregate_dbit_error = 0; /* Query ECC Status */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_STATUS, &val); if (ret != NvCtrlSuccess || val == NV_CTRL_GPU_ECC_STATUS_DISABLED) { ecc_enabled = FALSE; ecc_enabled_string = "Disabled"; } else { ecc_enabled = TRUE; ecc_enabled_string = "Enabled"; } ctk_ecc->ecc_enabled = ecc_enabled; /* Query ECC Configuration */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_CONFIGURATION, &val); if (ret != NvCtrlSuccess || val == NV_CTRL_GPU_ECC_CONFIGURATION_DISABLED) { ctk_ecc->ecc_configured = FALSE; } else { ctk_ecc->ecc_configured = TRUE; } /* get default status */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION, &val); if (ret != NvCtrlSuccess || val == NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_DISABLED) { ecc_default_status = FALSE; } else { ecc_default_status = TRUE; } /* Query ECC errors */ ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS, &sbit_error); if (ret != NvCtrlSuccess) { sbit_error_available = FALSE; } ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS, &dbit_error); if (ret != NvCtrlSuccess) { dbit_error_available = FALSE; } ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS, &aggregate_sbit_error); if (ret != NvCtrlSuccess) { aggregate_sbit_error_available = FALSE; } ret = NvCtrlGetAttribute64(ctrl_target, NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS, &aggregate_dbit_error); if (ret != NvCtrlSuccess) { aggregate_dbit_error_available = FALSE; } ctk_ecc->sbit_error_available = sbit_error_available; ctk_ecc->aggregate_sbit_error_available = aggregate_sbit_error_available; ctk_ecc->dbit_error_available = dbit_error_available; ctk_ecc->aggregate_dbit_error_available = aggregate_dbit_error_available; /* Query ECC configuration supported */ ret = NvCtrlGetAttribute(ctrl_target, NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED, &ecc_config_supported); if (ret != NvCtrlSuccess) { ecc_config_supported = 0; } /* set container properties for the CtkEcc widget */ gtk_box_set_spacing(GTK_BOX(ctk_ecc), 5); /* banner */ banner = ctk_banner_image_new(BANNER_ARTWORK_GPU); gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0); vbox = gtk_vbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(object), vbox, TRUE, TRUE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new("ECC Status"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); table = gtk_table_new(1, 2, FALSE); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); 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); /* ECC Status */ hbox2 = gtk_hbox_new(FALSE, 0); gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, row, row+1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new("ECC:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); eventbox = gtk_event_box_new(); gtk_table_attach(GTK_TABLE(table), eventbox, 1, 2, row, row+1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new(ecc_enabled_string); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_container_add(GTK_CONTAINER(eventbox), label); ctk_config_set_tooltip(ctk_config, eventbox, __ecc_status_help); ctk_ecc->status = label; row += 3; /* Add ECC Errors */ if (sbit_error_available && dbit_error_available) { ctk_ecc->sbit_error = add_table_int_row(ctk_config, table, __sbit_error_help, "Single-bit ECC Errors:", sbit_error, row, ecc_enabled); row += 1; // add vertical padding between rows ctk_ecc->dbit_error = add_table_int_row(ctk_config, table, __dbit_error_help, "Double-bit ECC Errors:", dbit_error, row, ecc_enabled); row += 3; // add vertical padding between rows } if (aggregate_sbit_error_available && aggregate_dbit_error_available) { ctk_ecc->aggregate_sbit_error = add_table_int_row(ctk_config, table, __aggregate_sbit_error_help, "Aggregate Single-bit ECC Errors:", aggregate_sbit_error, row, ecc_enabled); row += 1; // add vertical padding between rows ctk_ecc->aggregate_dbit_error = add_table_int_row(ctk_config, table, __aggregate_dbit_error_help, "Aggregate Double-bit ECC Errors:", aggregate_dbit_error, row, ecc_enabled); } /* ECC configuration settings */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new("ECC Configuration"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); hsep = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hsep, TRUE, TRUE, 5); hbox2 = gtk_hbox_new(FALSE, 0); ctk_ecc->configuration_status = gtk_check_button_new_with_label("Enable ECC"); gtk_box_pack_start(GTK_BOX(hbox2), ctk_ecc->configuration_status, FALSE, FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox2), 5); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctk_ecc->configuration_status), ctk_ecc->ecc_configured); ctk_config_set_tooltip(ctk_config, ctk_ecc->configuration_status, __configuration_status_help); g_signal_connect(G_OBJECT(ctk_ecc->configuration_status), "clicked", G_CALLBACK(ecc_config_button_toggled), (gpointer) ctk_ecc); g_signal_connect(G_OBJECT(ctk_event), CTK_EVENT_NAME(NV_CTRL_GPU_ECC_CONFIGURATION), G_CALLBACK(ecc_configuration_update_received), (gpointer) ctk_ecc); gtk_widget_set_sensitive(ctk_ecc->configuration_status, ecc_config_supported); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(ctk_ecc), hbox, FALSE, FALSE, 0); /* Add buttons */ if (sbit_error_available && dbit_error_available) { ctk_ecc->clear_button = gtk_button_new_with_label("Clear ECC Errors"); gtk_box_pack_end(GTK_BOX(hbox), ctk_ecc->clear_button, FALSE, FALSE, 0); ctk_config_set_tooltip(ctk_config, ctk_ecc->clear_button, __clear_button_help); gtk_widget_set_sensitive(ctk_ecc->clear_button, ecc_enabled); g_signal_connect(G_OBJECT(ctk_ecc->clear_button), "clicked", G_CALLBACK(clear_ecc_errors_button_clicked), (gpointer) ctk_ecc); } if (aggregate_sbit_error_available && aggregate_dbit_error_available) { ctk_ecc->clear_aggregate_button = gtk_button_new_with_label("Clear Aggregate ECC Errors"); gtk_box_pack_end(GTK_BOX(hbox), ctk_ecc->clear_aggregate_button, FALSE, FALSE, 0); ctk_config_set_tooltip(ctk_config, ctk_ecc->clear_button, __clear_aggregate_button_help); gtk_widget_set_sensitive(ctk_ecc->clear_aggregate_button, ecc_enabled); g_signal_connect(G_OBJECT(ctk_ecc->clear_aggregate_button), "clicked", G_CALLBACK(clear_aggregate_ecc_errors_button_clicked), (gpointer) ctk_ecc); } ctk_ecc->reset_default_config_button = gtk_button_new_with_label("Reset Default Configuration"); eventbox = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(eventbox), ctk_ecc->reset_default_config_button); gtk_box_pack_end(GTK_BOX(hbox), eventbox, FALSE, FALSE, 5); ctk_config_set_tooltip(ctk_config, ctk_ecc->reset_default_config_button, __reset_default_config_button_help); gtk_widget_set_sensitive(ctk_ecc->reset_default_config_button, ecc_config_supported && (ecc_enabled != ecc_default_status)); g_signal_connect(G_OBJECT(ctk_ecc->reset_default_config_button), "clicked", G_CALLBACK(reset_default_config_button_clicked), (gpointer) ctk_ecc); /* Register a timer callback to update Ecc status info */ str = g_strdup_printf("ECC Settings (GPU %d)", NvCtrlGetTargetId(ctrl_target)); ctk_config_add_timer(ctk_ecc->ctk_config, DEFAULT_UPDATE_ECC_STATUS_INFO_TIME_INTERVAL, str, (GSourceFunc) update_ecc_info, (gpointer) ctk_ecc); g_free(str); gtk_widget_show_all(GTK_WIDGET(ctk_ecc)); update_ecc_info(ctk_ecc); return GTK_WIDGET(ctk_ecc); }
/* - ctk_event_register_source() * * Keep track of event sources globally to support * dispatching events on a dpy to multiple CtkEvent * objects. Since the driver only sends out one event * notification per dpy (client), there should only be one * event source attached per unique dpy. When an event * is received, the dispatching function should then * emit a signal to every CtkEvent object that * requests event notification from the dpy for the * given target type/id (X screen, GPU etc). */ static void ctk_event_register_source(CtkEvent *ctk_event) { Display *dpy = NvCtrlGetDisplayPtr(ctk_event->handle); CtkEventSource *event_source; CtkEventNode *event_node; if (!dpy) { return; } /* Do we already have an event source for this dpy? */ event_source = event_sources; while (event_source) { if (event_source->dpy == dpy) { break; } event_source = event_source->next; } /* create a new input source */ if (!event_source) { GSource *source; static GSourceFuncs ctk_source_funcs = { ctk_event_prepare, ctk_event_check, ctk_event_dispatch, NULL, /* finalize */ NULL, /* closure_callback */ NULL, /* closure_marshal */ }; source = g_source_new(&ctk_source_funcs, sizeof(CtkEventSource)); event_source = (CtkEventSource *) source; if (!event_source) { return; } event_source->dpy = dpy; event_source->event_poll_fd.fd = ConnectionNumber(dpy); event_source->event_poll_fd.events = G_IO_IN; event_source->event_base = NvCtrlGetEventBase(ctk_event->handle); event_source->randr_event_base = NvCtrlGetXrandrEventBase(ctk_event->handle); /* add the input source to the glib main loop */ g_source_add_poll(source, &event_source->event_poll_fd); g_source_attach(source, NULL); /* add the source to the global list of sources */ event_source->next = event_sources; event_sources = event_source; } /* Add the ctk_event object to the source's list of event objects */ event_node = (CtkEventNode *)g_malloc(sizeof(CtkEventNode)); if (!event_node) { return; } event_node->ctk_event = ctk_event; event_node->target_type = NvCtrlGetTargetType(ctk_event->handle); event_node->target_id = NvCtrlGetTargetId(ctk_event->handle); event_node->next = event_source->ctk_events; event_source->ctk_events = event_node; /* * This next bit of code is to make sure that the randr_event_base * for this event source is valid in the case where a NON X Screen * target type handle is used to create the initial event source * (Resulting in randr_event_base being == -1), followed by an * X Screen target type handle registering itself to receive * XRandR events on the existing dpy/event source. */ if (event_source->randr_event_base == -1 && event_node->target_type == NV_CTRL_TARGET_TYPE_X_SCREEN) { event_source->randr_event_base = NvCtrlGetXrandrEventBase(ctk_event->handle); } } /* ctk_event_register_source() */
/* - ctk_event_register_source() * * Keep track of event sources globally to support * dispatching events on an event handle to multiple CtkEvent * objects. Since the driver only sends out one event * notification per event handle (client), there should only be one * event source attached per unique event handle. When an event * is received, the dispatching function should then * emit a signal to every CtkEvent object that * requests event notification from the event handle for the * given target type/id (X screen, GPU etc). */ static void ctk_event_register_source(CtkEvent *ctk_event) { CtrlTarget *ctrl_target = ctk_event->ctrl_target; NvCtrlEventHandle *event_handle = NvCtrlGetEventHandle(ctrl_target); CtkEventSource *event_source; CtkEventNode *event_node; if (!event_handle) { return; } /* Do we already have an event source for this event handle? */ event_source = find_event_source(event_handle); /* create a new input source */ if (!event_source) { GSource *source; int event_fd; static GSourceFuncs ctk_source_funcs = { ctk_event_prepare, ctk_event_check, ctk_event_dispatch, NULL, /* finalize */ NULL, /* closure_callback */ NULL, /* closure_marshal */ }; source = g_source_new(&ctk_source_funcs, sizeof(CtkEventSource)); event_source = (CtkEventSource *) source; if (!event_source) { return; } NvCtrlEventHandleGetFD(event_handle, &event_fd); event_source->event_handle = event_handle; event_source->event_poll_fd.fd = event_fd; event_source->event_poll_fd.events = G_IO_IN; /* add the input source to the glib main loop */ g_source_add_poll(source, &event_source->event_poll_fd); g_source_attach(source, NULL); /* add the source to the global list of sources */ event_source->next = event_sources; event_sources = event_source; } /* Add the ctk_event object to the source's list of event objects */ event_node = (CtkEventNode *)g_malloc(sizeof(CtkEventNode)); if (!event_node) { return; } event_node->ctk_event = ctk_event; event_node->target_type = NvCtrlGetTargetType(ctrl_target); event_node->target_id = NvCtrlGetTargetId(ctrl_target); event_node->next = event_source->ctk_events; event_source->ctk_events = event_node; } /* ctk_event_register_source() */
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() */
/* * 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); }
/* * CTK VCS (Visual Computing System) widget creation * */ GtkWidget* ctk_vcs_new(NvCtrlAttributeHandle *handle, CtkConfig *ctk_config) { GObject *object; CtkVcs *ctk_object; GtkWidget *label; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *event; GtkWidget *banner; GtkWidget *hseparator; GtkWidget *table; GtkWidget *scrollWin; GtkWidget *checkbutton; gchar *product_name; gchar *serial_number; gchar *build_date; gchar *product_id; gchar *firmware_version; gchar *hardware_version; gint current_row; gboolean high_perf_mode; ReturnStatus ret; gchar *s; char *psu_str = NULL; PSUEntry psuEntry; GtkWidget *vbox_scroll, *hbox_scroll; /* * get the static string data that we will display below */ /* Product Name */ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VCSC_PRODUCT_NAME, &product_name); if (ret != NvCtrlSuccess) { product_name = g_strdup("Unable to determine"); } /* Serial Number */ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VCSC_SERIAL_NUMBER, &serial_number); if (ret != NvCtrlSuccess) { serial_number = g_strdup("Unable to determine"); } /* Build Date */ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VCSC_BUILD_DATE, &build_date); if (ret != NvCtrlSuccess) { build_date = g_strdup("Unable to determine"); } /* Product ID */ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VCSC_PRODUCT_ID, &product_id); if (ret != NvCtrlSuccess) { product_id = g_strdup("Unable to determine"); } /* Firmware Version */ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VCSC_FIRMWARE_VERSION, &firmware_version); if (ret != NvCtrlSuccess) { firmware_version = g_strdup("Unable to determine"); } /* Hardware Version */ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VCSC_HARDWARE_VERSION, &hardware_version); if (ret != NvCtrlSuccess) { hardware_version = g_strdup("Unable to determine"); } /* now, create the object */ object = g_object_new(CTK_TYPE_VCS, NULL); ctk_object = CTK_VCS(object); /* cache the attribute handle */ ctk_object->handle = handle; ctk_object->ctk_config = ctk_config; /* set container properties of the object */ gtk_box_set_spacing(GTK_BOX(ctk_object), 10); /* banner */ banner = ctk_banner_image_new(BANNER_ARTWORK_VCS); gtk_box_pack_start(GTK_BOX(ctk_object), banner, FALSE, FALSE, 0); /* * This displays basic System information, including * display name, Operating system type and the NVIDIA driver version. */ vbox = gtk_vbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(ctk_object), vbox, TRUE, TRUE, 0); /* General purpose error dialog */ ctk_object->error_dialog = create_error_dialog(ctk_object); if (NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_VCSC_HIGH_PERF_MODE, &high_perf_mode) == NvCtrlSuccess) { hbox = gtk_hbox_new(FALSE, 0); checkbutton = gtk_check_button_new_with_label("Enable High Performance Mode"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), high_perf_mode); g_signal_connect(G_OBJECT(checkbutton), "toggled", G_CALLBACK(vcs_perf_checkbox_toggled), (gpointer) ctk_object); gtk_box_pack_start(GTK_BOX(hbox), checkbutton, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); } /* Create the Scrolling Window */ scrollWin = gtk_scrolled_window_new(NULL, NULL); hbox_scroll = gtk_hbox_new(FALSE, 0); vbox_scroll = gtk_vbox_new(FALSE, 5); event = gtk_event_box_new(); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_widget_modify_fg(event, GTK_STATE_NORMAL, &(event->style->text[GTK_STATE_NORMAL])); gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(event->style->base[GTK_STATE_NORMAL])); gtk_container_add(GTK_CONTAINER(event), hbox_scroll); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin), event); gtk_box_pack_start(GTK_BOX(hbox_scroll), vbox_scroll, TRUE, TRUE, 5); gtk_widget_set_size_request(scrollWin, -1, 50); gtk_box_pack_start(GTK_BOX(vbox), scrollWin, TRUE, TRUE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0); label = gtk_label_new("VCS Information"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); table = gtk_table_new(5, 2, FALSE); gtk_box_pack_start(GTK_BOX(vbox_scroll), table, FALSE, FALSE, 0); 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); add_table_row(table, 0, 0, 0.5, "Product Name:", 0, 0.5, product_name); add_table_row(table, 1, 0, 0.5, "Serial Number:", 0, 0.5, serial_number); add_table_row(table, 2, 0, 0.5, "Build Date:", 0, 0.5, build_date); add_table_row(table, 3, 0, 0.5, "Product ID:", 0, 0.5, product_id); add_table_row(table, 4, 0, 0.5, "Firmware version:", 0, 0.5, firmware_version); add_table_row(table, 5, 0, 0.5, "Hardware version:", 0, 0.5, hardware_version); g_free(product_name); g_free(serial_number); g_free(build_date); g_free(product_id); g_free(firmware_version); g_free(hardware_version); /* Query Canoas 2.0 specific details */ if ((NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_VCSC_HIGH_PERF_MODE, &high_perf_mode) == NvCtrlSuccess) && (NvCtrlGetStringAttribute(ctk_object->handle, NV_CTRL_STRING_VCSC_PSU_INFO, &psu_str) == NvCtrlSuccess)) { GtkWidget *vbox_padding; /* Show the additonal queried information */ /* Populate scrolling window with data */ vbox_padding = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_scroll), vbox_padding, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0); label = gtk_label_new("VCS Thermal Information"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); table = gtk_table_new(3, 2, FALSE); gtk_box_pack_start(GTK_BOX(vbox_scroll), table, FALSE, FALSE, 0); 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); label = gtk_label_new("Intake Temperature:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new(NULL); 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); ctk_object->intake_temp = label; label = gtk_label_new("Exhaust Temperature:"); /* This is the current largest label. Get its size */ gtk_widget_size_request(label, &ctk_object->req); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 1, 2, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); ctk_object->exhaust_temp = label; label = gtk_label_new("Board Temperature:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 2, 3, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); ctk_object->board_temp = label; /* Populate table for PSU information */ psuEntry.psu_current = -1; psuEntry.psu_power = -1; psuEntry.psu_voltage = -1; psuEntry.psu_state = -1; if (psu_str) { parse_token_value_pairs(psu_str, apply_psu_entry_token, &psuEntry); } vbox_padding = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_scroll), vbox_padding, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0); label = gtk_label_new("VCS Power Supply Unit Information"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); table = gtk_table_new(4, 2, FALSE); gtk_box_pack_start(GTK_BOX(vbox_scroll), table, FALSE, FALSE, 0); 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); label = gtk_label_new("PSU State:"); 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(NULL); 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); ctk_object->psu_state = label; label = gtk_label_new("PSU Current:"); 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, 1, 2, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); label = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 1, 2, GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0); ctk_object->psu_current = label; current_row = 2; if (psuEntry.psu_power != -1) { label = gtk_label_new("PSU Power:"); 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); label = gtk_label_new(NULL); 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); ctk_object->psu_power = label; current_row++; } if (psuEntry.psu_voltage != -1) { label = gtk_label_new("PSU Voltage:"); 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); label = gtk_label_new(NULL); 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); ctk_object->psu_voltage = label; } /* Create container for fan status table */ vbox_padding = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_scroll), vbox_padding, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0); label = gtk_label_new("VCS Fan Status"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); hseparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_scroll), hbox, FALSE, FALSE, 0); ctk_object->fan_status_container = hbox; /* Register a timer callback to update the dynamic information */ s = g_strdup_printf("VCS Monitor (VCS %d)", NvCtrlGetTargetId(ctk_object->handle)); ctk_config_add_timer(ctk_object->ctk_config, DEFAULT_UPDATE_VCS_INFO_TIME_INTERVAL, s, (GSourceFunc) update_vcs_info, (gpointer) ctk_object); g_free(s); update_vcs_info(ctk_object); } gtk_widget_show_all(GTK_WIDGET(object)); return GTK_WIDGET(object); }