/* returns the value of the sensor */ static gdouble nvidia_plugin_get_sensor_value(const gchar *path, const gchar *id, SensorType type, GError **error) { Bool res; int temp; int i; i = g_ascii_strtoll(id + strlen("GPU"), NULL, 10); if (g_ascii_strcasecmp(path, THERMAL_SENSOR_TEMP) == 0) { res = XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_THERMAL_SENSOR, i, 0, NV_CTRL_THERMAL_SENSOR_READING, &temp); } else if (g_ascii_strcasecmp(path, THERMAL_COOLER_LEVEL) == 0) { res = XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_COOLER, i, 0, NV_CTRL_THERMAL_COOLER_LEVEL, &temp); } else if (g_ascii_strcasecmp(path, GPU_CORE_TEMP) == 0) { res = XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_GPU_CORE_TEMPERATURE, &temp); } else if (g_ascii_strcasecmp(path, AMBIENT_TEMP) == 0) { res = XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_AMBIENT_TEMPERATURE, &temp); } else { g_set_error(error, SENSORS_APPLET_PLUGIN_ERROR, 0, "Invalid path string passed to nvidia_plugin_get_sensor_value"); return 0; } if (res != True) { /* when res isn't true something went wrong */ g_set_error(error, SENSORS_APPLET_PLUGIN_ERROR, 0, "XNVCTRLQueryAttribute returned false"); return 0; } /* convert the int to gdouble and return it */ return (gdouble)temp; }
std::string* glxosdPluginDataProvider(glxosd::GLXOSD *glxosdInstance) { if (!errorResult.empty()) { return new std::string(errorResult); } std::stringstream stringBuilder; for (int i = 0; i < numberOfGpus; i++) { int temperature; if ((XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_GPU_CORE_TEMPERATURE, &temperature) != True)) { stringBuilder << (boost::format(nvidiaGPUFormat)) % "unknown" % i % "failed to get the temperature!"; } else { stringBuilder << boost::format(nvidiaGPUFormat) % displayNames[i] % i % (boost::format( glxosdInstance->getConfigurationManager().getProperty< boost::format>( "temperature_format")) % temperature); } } return new std::string(stringBuilder.str()); }
Bool XNVCTRLQueryAttribute ( Display *dpy, int screen, unsigned int display_mask, unsigned int attribute, int *value ) { return XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, display_mask, attribute, value); }
static int wait_for_perflvl(Display *dpy, uint8_t wanted_perflvl) { unsigned long start_time, get_time; struct timeval tv; int cur_perflvl = -1, tmp; gettimeofday(&tv, NULL); start_time = tv.tv_sec; fprintf(stderr, "XNVCTRLQueryTargetAttribute\n"); XNVCTRLQueryTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_GPU, 0, 0, NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE , &tmp); if (tmp != NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_ENABLED) { fprintf(stderr, "ERROR - Driver not in Adaptive state\n"); return 1; } do { gettimeofday(&tv, NULL); get_time = tv.tv_sec; if ((start_time + NOUVEAU_TIME_WAIT) < get_time ) { fprintf(stderr, "ERROR - Timeout\n"); return 2; } XNVCTRLQueryTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, 0, 0, NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL, &tmp); if (cur_perflvl < 0) { cur_perflvl = tmp; fprintf(stderr, "NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL = %d\n", cur_perflvl); } else if (tmp != cur_perflvl) { cur_perflvl = tmp; fprintf(stderr, "Changed NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL = %d\n", cur_perflvl); } } while ( cur_perflvl != wanted_perflvl ); return 0; }
static int upclock_card(Display *dpy) { unsigned long start_time, get_time; struct timeval tv; int cur_perflvl = -1, tmp; gettimeofday(&tv, NULL); start_time = tv.tv_sec; XNVCTRLQueryTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, 0, 0, NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL, &cur_perflvl); pid_t pid = fork(); if (pid == 0) { exit (system("timeout 3 glxgears")); } else if (pid == -1) { fprintf(stderr, "Fork failed! Abort\n"); exit (4); } sleep(1); do { usleep(10000); /* 10 ms */ gettimeofday(&tv, NULL); get_time = tv.tv_sec; XNVCTRLQueryTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, 0, 0, NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE, &tmp); } while ( tmp != NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_MAXPERF && (start_time + 2) < get_time); kill(pid, SIGTERM); waitpid(pid, NULL, 0); return 0; }
static void update_sensor_value(IsSensor *sensor, IsNvidiaPlugin *self) { IsNvidiaPluginPrivate *priv; const gchar *path; guint i; priv = self->priv; path = is_sensor_get_path(sensor); for (i = 0; i < G_N_ELEMENTS(map); i++) { Bool ret; int value; int idx; if (g_strrstr(path, map[i].description) == NULL) { continue; } idx = g_ascii_strtoll(g_strrstr(path, map[i].description) + strlen(map[i].description), NULL, 10); ret = XNVCTRLQueryTargetAttribute(priv->display, map[i].target, idx, 0, map[i].attribute, &value); if (!ret) { GError *error = g_error_new(g_quark_from_string("nvidia-plugin-error-quark"), 0, /* first placeholder is * sensor name */ _("Error getting sensor value for sensor %s"), path); is_sensor_emit_error(sensor, error); g_error_free(error); continue; } if (IS_IS_TEMPERATURE_SENSOR(sensor)) { is_temperature_sensor_set_celsius_value(IS_TEMPERATURE_SENSOR(sensor), value); } else { is_sensor_set_value(sensor, value); } } }
/* * do_query() * * Prints information for all GVI devices found on * the given X server. * */ static void do_query(Display *dpy, int use_gvi) { Bool ret; int num_gvi; int gvi; int last_gvi; int value; int num_jacks; int jack; int max_channels_per_jack; int channel; char *pOut; /* Query the number of GVI devices on the server */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_GVI, &num_gvi); if (!ret) { printf("Failed to query number of GVI devices!\n"); return; } printf("Found %d GVI device(s) on server.\n", num_gvi); if ( !num_gvi ) { return; } if (use_gvi >= 0 && use_gvi < num_gvi) { /* Only display information about 1 GVI device/ */ printf("Querying GVI device %d...\n", use_gvi); gvi = use_gvi; last_gvi = use_gvi; } else { /* Display all GVI devices */ printf("Querying all GVI devices...\n"); gvi = 0; last_gvi = num_gvi-1; } /* Display information about the GVI(s) */ for (; gvi <= last_gvi; gvi++) { printf("\n"); printf("- GVI Board %d :\n", gvi); ret = XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_STRING_GVIO_FIRMWARE_VERSION, &pOut); if (!ret) { printf(" - Failed to query firmware version of GVI %d.\n", gvi); continue; } printf(" - Firmware Version: %s\n", pOut); XFree(pOut); pOut = NULL; ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVI_GLOBAL_IDENTIFIER, &value); if (!ret) { printf(" - Failed to query global ID of GVI %d.\n", gvi); continue; } printf(" - Global ID: %d\n", value); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVI_NUM_CAPTURE_SURFACES, &value); if (!ret) { printf(" - Failed to number of capture surfaces of GVI %d.\n", gvi); continue; } printf(" - Number of capture surfaces: %d\n", value); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, &value); if (!ret) { printf(" - Failed to query requested video format on " "GVI %d.\n", gvi); continue; } printf(" - Requested video format: %d (%s)\n", value, VideoFormatName(value)); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVI_MAX_STREAMS, &value); if (!ret) { printf(" - Failed to query max number of streams on " "GVI %d.\n", gvi); continue; } printf(" - Max number of configurable streams: %d\n", value); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVI_MAX_LINKS_PER_STREAM, &value); if (!ret) { printf(" - Failed to query max number of links per stream on " "GVI %d.\n", gvi); continue; } printf(" - Max number of links per stream: %d\n", value); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVI_NUM_JACKS, &num_jacks); if (!ret) { printf(" - Failed to query number of input jacks on GVI " "%d.\n", gvi); continue; } printf(" - Number of input jacks on device: %d\n", num_jacks); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_GVI_MAX_CHANNELS_PER_JACK, &max_channels_per_jack); if (!ret) { printf(" - Failed to query maximum number of channels per " "jack on GVI %d.\n", gvi); continue; } printf(" - Maximum number of channels per jack on device: %d\n", max_channels_per_jack); /* Display per-jack/channel information */ for (jack = 0; jack < num_jacks; jack++) { printf(" - Jack %d\n", jack); for (channel = 0; channel < max_channels_per_jack; channel++) { printf(" - Channel %d\n", channel); unsigned int link_definition = ((channel & 0xFFFF)<<16); link_definition |= (jack & 0xFFFF); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id link_definition, // display_mask NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT, &value); if (!ret) { printf(" - Failed to query detected video format " "on jack %d, channel %d of GVI %d.\n", jack, channel, gvi); continue; } printf(" - Detected Video Format: %d (%s)\n", value, VideoFormatName(value) ); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id link_definition, // display_mask NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER, &value); if (!ret) { printf(" - Failed to query detected SMPTE352 " "Identifier on jack %d, channel %d of GVI %d.\n", jack, channel, gvi); continue; } printf(" - Detected SMPTE352 Identifier: 0x%08x\n", value); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id link_definition, // display_mask NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT, &value); if (!ret) { printf(" - Failed to query detected bits per " "component on jack %d, channel %d of GVI %d.\n", jack, channel, gvi); continue; } printf(" - Detected bits per component: "); switch (value) { case NV_CTRL_GVI_BITS_PER_COMPONENT_8: printf("8"); break; case NV_CTRL_GVI_BITS_PER_COMPONENT_10: printf("10"); break; case NV_CTRL_GVI_BITS_PER_COMPONENT_12: printf("12"); break; case NV_CTRL_GVI_BITS_PER_COMPONENT_UNKNOWN: /* Fall Through */ default: printf("Unknown"); break; } printf("\n"); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id link_definition, // display_mask NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING, &value); if (!ret) { printf(" - Failed to query detected component " "sampling on jack %d, channel %d of GVI %d.\n", jack, channel, gvi); continue; } printf(" - Detected component sampling: "); switch (value) { case NV_CTRL_GVI_COMPONENT_SAMPLING_4444: printf("4:4:4:4"); break; case NV_CTRL_GVI_COMPONENT_SAMPLING_4224: printf("4:2:2:4"); break; case NV_CTRL_GVI_COMPONENT_SAMPLING_444: printf("4:4:4"); break; case NV_CTRL_GVI_COMPONENT_SAMPLING_422: printf("4:2:2"); break; case NV_CTRL_GVI_COMPONENT_SAMPLING_420: printf("4:2:0"); break; case NV_CTRL_GVI_COMPONENT_SAMPLING_UNKNOWN: /* Fall Through */ default: printf("Unknown"); break; } printf("\n"); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id link_definition, // display_mask NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE, &value); if (!ret) { printf(" - Failed to query detected color space on " "jack %d, channel %d of GVI %d.\n", jack, channel, gvi); continue; } printf(" - Detected color space: "); switch (value) { case NV_CTRL_GVI_COLOR_SPACE_GBR: printf("GBR"); break; case NV_CTRL_GVI_COLOR_SPACE_GBRA: printf("GBRA"); break; case NV_CTRL_GVI_COLOR_SPACE_GBRD: printf("GBRD"); break; case NV_CTRL_GVI_COLOR_SPACE_YCBCR: printf("YCbCr"); break; case NV_CTRL_GVI_COLOR_SPACE_YCBCRA: printf("YCbCrA"); break; case NV_CTRL_GVI_COLOR_SPACE_YCBCRD: printf("YCbCrD"); break; case NV_CTRL_GVI_COLOR_SPACE_UNKNOWN: /* Fall Through */ default: printf("Unknown"); break; } printf("\n"); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id link_definition, // display_mask NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID, &value); if (!ret) { printf(" - Failed to query detected link ID on " "jack %d, channel %d of GVI %d.\n", jack, channel, gvi); continue; } printf(" - Detected Link ID: Link %d", value); if (value == NV_CTRL_GVI_LINK_ID_UNKNOWN) { printf(" (Unknown)"); } else if (value < 26) { printf(" (Link%c)", (int)('A')+value); } printf("\n"); } /* Done querying per-channel information */ } /* Done querying per-jack information */ /* Query stream (link to jack+channel) topology */ ret = XNVCTRLStringOperation(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS, NULL, // pIn &pOut); if (!ret || !pOut) { printf(" - Failed to query stream topology configuration of " "GVI %d.\n", gvi); continue; } printf(" - Topology:\n"); printf("\n %s\n\n", pOut ? pOut : "No streams are configured."); /* Query per-stream settings */ if (pOut) { char *str = pOut; int i = 0; while ( (str = strstr(str, "stream=")) ) { printf(" - Stream %d\n", i); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id i, // display_mask (stream #) NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT, &value); if (!ret) { printf(" - Failed to query requested stream bits per component " "for stream %d of GVI %d.\n", i, gvi); continue; } printf(" - Requested bits per component: %d (%s)\n", value, BPCName(value)); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id i, // display_mask (stream #) NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING, &value); if (!ret) { printf(" - Failed to query requested stream component sampling " "for stream %d of GVI %d.\n", i, gvi); continue; } printf(" - Requested component sampling: %d (%s)\n", value, SamplingName(value)); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id i, // display_mask (stream #) NV_CTRL_GVI_REQUESTED_STREAM_CHROMA_EXPAND, &value); if (!ret) { printf(" - Failed to query requested stream chroma expand " "for stream %d of GVI %d.\n", i, gvi); continue; } printf(" - Requested chroma expand: %s\n", value ? "Enabled" : "Disabled"); i++; str++; } } XFree(pOut); pOut = NULL; } /* Done Querying information about GVI devices */ } /* do_query() */
/** * load initial data * * TODO:350:M: Implement nvCtrlTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * nvCtrlTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int nvCtrlTable_container_load(netsnmp_container *container) { nvCtrlTable_rowreq_ctx *rowreq_ctx; size_t count = 0; Display *dpy; Bool ret; int event_base, error_base, major, minor, gpus; int gpu, retval, len; char *str; DEBUGMSGTL(("verbose:nvCtrlTable:nvCtrlTable_container_load", "called\n")); /* * open a connection to the X server indicated by the DISPLAY * environment variable */ dpy = XOpenDisplay(NULL); if (!dpy) { DEBUGMSGTL(("nvCtrlTable:nvCtrlTable_container_load", "Cannot open display '%s'.\n", XDisplayName(NULL))); return MFD_RESOURCE_UNAVAILABLE; } /* * check if the NV-CONTROL X extension is present on this X server */ ret = XNVCTRLQueryExtension(dpy, &event_base, &error_base); if (ret != True) { DEBUGMSGTL(("nvCtrlTable:nvCtrlTable_container_load", "The NV-CONTROL X extension does not exist on '%s'.\n", XDisplayName(NULL))); return MFD_RESOURCE_UNAVAILABLE; } /* * query the major and minor extension version */ ret = XNVCTRLQueryVersion(dpy, &major, &minor); if (ret != True) { DEBUGMSGTL(("nvCtrlTable:nvCtrlTable_container_load", "The NV-CONTROL X extension does not exist on '%s'.\n", XDisplayName(NULL))); return MFD_RESOURCE_UNAVAILABLE; } /* * query number of GPUs via the NV-CONTROL X extension; then, allocate * a rowreq context, set the index(es) and data, and insert into the * container. */ if (!XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_GPU, &gpus)) { snmp_log(LOG_ERR, "failed to query number of GPUs\n"); return MFD_ERROR; } for (gpu = 0; gpu < gpus; gpu++) { rowreq_ctx = nvCtrlTable_allocate_rowreq_ctx(); if (NULL == rowreq_ctx) { snmp_log(LOG_ERR, "memory allocation failed\n"); return MFD_RESOURCE_UNAVAILABLE; } if (MFD_SUCCESS != nvCtrlTable_indexes_set(rowreq_ctx, gpu)) { snmp_log(LOG_ERR, "error setting index while loading" "nvCtrlTable data.\n"); nvCtrlTable_release_rowreq_ctx(rowreq_ctx); continue; } /* * setup/save data for nvCtrlProductName * nvCtrlProductName(2)/DisplayString/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H */ ret = XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_STRING_PRODUCT_NAME, &str); if (ret) { len = strlen(str); if (sizeof(rowreq_ctx->data.nvCtrlProductName) < len) { snmp_log(LOG_ERR,"not enough space for value\n"); return MFD_ERROR; } rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_PRODUCT_NAME_FLAG; rowreq_ctx->data.nvCtrlProductName_len = len; memcpy(rowreq_ctx->data.nvCtrlProductName, str, len); XFree(str); } /* * setup/save data for nvCtrlVBiosVersion * nvCtrlVBiosVersion(3)/DisplayString/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H */ ret = XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_STRING_VBIOS_VERSION, &str); if (ret) { len = strlen(str); if (sizeof(rowreq_ctx->data.nvCtrlVBiosVersion) < len) { snmp_log(LOG_ERR,"not enough space for value\n"); return MFD_ERROR; } rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_VBIOS_VERSION_FLAG; rowreq_ctx->data.nvCtrlVBiosVersion_len = len; memcpy(rowreq_ctx->data.nvCtrlVBiosVersion, str, len); XFree(str); } /* * setup/save data for nvCtrlNvidiaDriverVersion * nvCtrlNvidiaDriverVersion(4)/DisplayString/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H */ ret = XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &str); if (ret) { len = strlen(str); if (sizeof(rowreq_ctx->data.nvCtrlNvidiaDriverVersion) < len) { snmp_log(LOG_ERR,"not enough space for value\n"); return MFD_ERROR; } rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_NVIDIA_DRIVER_VERSION_FLAG; rowreq_ctx->data.nvCtrlNvidiaDriverVersion_len = len; memcpy(rowreq_ctx->data.nvCtrlNvidiaDriverVersion, str, len); XFree(str); } /* * setup/save data for nvCtrlVersion * nvCtrlVersion(5)/DisplayString/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H */ rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_VERSION_FLAG; snprintf(rowreq_ctx->data.nvCtrlVersion, sizeof(rowreq_ctx->data.nvCtrlVersion), "%d.%d", major, minor); rowreq_ctx->data.nvCtrlVersion_len = strlen(rowreq_ctx->data.nvCtrlVersion); /* * setup/save data for nvCtrlBusType * nvCtrlBusType(6)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_BUS_TYPE, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_BUS_TYPE_FLAG; rowreq_ctx->data.nvCtrlBusType = retval; } /* * setup/save data for nvCtrlBusRate * nvCtrlBusRate(7)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_BUS_RATE, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_BUS_RATE_FLAG; rowreq_ctx->data.nvCtrlBusRate = retval; } /* * setup/save data for nvCtrlVideoRam * nvCtrlVideoRam(8)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_VIDEO_RAM, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_VIDEO_RAM_FLAG; rowreq_ctx->data.nvCtrlVideoRam = retval; } /* * setup/save data for nvCtrlIrq * nvCtrlIrq(9)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_IRQ, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_IRQ_FLAG; rowreq_ctx->data.nvCtrlIrq = retval; } /* * setup/save data for nvCtrlGPUCoreTemp * nvCtrlGPUCoreTemp(10)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_CORE_TEMPERATURE, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_CORE_TEMP_FLAG; rowreq_ctx->data.nvCtrlGPUCoreTemp = retval; } /* * setup/save data for nvCtrlGPUCoreThreshold * nvCtrlGPUCoreThreshold(11)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_CORE_THRESHOLD, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_CORE_THRESHOLD_FLAG; rowreq_ctx->data.nvCtrlGPUCoreThreshold = retval; } /* * setup/save data for nvCtrlGPUDefaultCoreThreshold * nvCtrlGPUDefaultCoreThreshold(12)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD_FLAG; rowreq_ctx->data.nvCtrlGPUDefaultCoreThreshold = retval; } /* * setup/save data for nvCtrlGPUMaxCoreThreshold * nvCtrlGPUMaxCoreThreshold(13)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_MAX_CORE_THRESHOLD, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_MAX_CORE_THRESHOLD_FLAG; rowreq_ctx->data.nvCtrlGPUMaxCoreThreshold = retval; } /* * setup/save data for nvCtrlGPUAmbientTemp * nvCtrlGPUAmbientTemp(14)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_AMBIENT_TEMPERATURE, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_AMBIENT_TEMP_FLAG; rowreq_ctx->data.nvCtrlGPUAmbientTemp = retval; } /* * setup/save data for nvCtrlGPUOverclockingState * nvCtrlGPUOverclockingState(15)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_OVERCLOCKING_STATE, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_OVERCLOCKING_STATE_FLAG; rowreq_ctx->data.nvCtrlGPUOverclockingState = retval; } /* * setup/save data for nvCtrlGPU2DGPUClockFreq * nvCtrlGPU2DGPUClockFreq(16)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_2D_CLOCK_FREQS, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_2D_GPU_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPU2DGPUClockFreq = (retval >> 16) & 0xFFFF; } /* * setup/save data for nvCtrlGPU2DMemClockFreq * nvCtrlGPU2DMemClockFreq(17)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_2D_MEM_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPU2DMemClockFreq = retval & 0xFFFF; } /* * setup/save data for nvCtrlGPU3DGPUClockFreq * nvCtrlGPU3DGPUClockFreq(18)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_3D_CLOCK_FREQS, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_3D_GPU_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPU3DGPUClockFreq = (retval >> 16) & 0xFFFF; } /* * setup/save data for nvCtrlGPU3DMemClockFreq * nvCtrlGPU3DMemClockFreq(19)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_3D_MEM_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPU3DMemClockFreq = retval & 0xFFFF; } /* * setup/save data for nvCtrlGPUDefault2DGPUClockFreq * nvCtrlGPUDefault2DGPUClockFreq(20)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_DEFAULT_2D_GPU_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPUDefault2DGPUClockFreq = (retval >> 16) & 0xFFFF; } /* * setup/save data for nvCtrlGPUDefault2DMemClockFreq * nvCtrlGPUDefault2DMemClockFreq(21)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_DEFAULT_2D_MEM_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPUDefault2DMemClockFreq = retval & 0xFFFF; } /* * setup/save data for nvCtrlGPUDefault3DGPUClockFreq * nvCtrlGPUDefault3DGPUClockFreq(22)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_DEFAULT_3D_GPU_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPUDefault3DGPUClockFreq = (retval >> 16) & 0xFFFF; } /* * setup/save data for nvCtrlGPUDefault3DMemClockFreq * nvCtrlGPUDefault3DMemClockFreq(23)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_DEFAULT_3D_MEM_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPUDefault3DMemClockFreq = retval & 0xFFFF; } /* * setup/save data for nvCtrlGPUCurrentGPUClockFreq * nvCtrlGPUCurrentGPUClockFreq(24)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, 0, NV_CTRL_GPU_CURRENT_CLOCK_FREQS, &retval); if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_CURRENT_GPU_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPUCurrentGPUClockFreq = (retval >> 16) & 0xFFFF; } /* * setup/save data for nvCtrlGPUCurrentMemClockFreq * nvCtrlGPUCurrentMemClockFreq(25)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h */ if (ret) { rowreq_ctx->column_exists_flags |= COLUMN_NV_CTRL_GPU_CURRENT_MEM_CLOCK_FREQ_FLAG; rowreq_ctx->data.nvCtrlGPUCurrentMemClockFreq = retval & 0xFFFF; } /* * insert into table container */ CONTAINER_INSERT(container, rowreq_ctx); ++count; } /* * close the display connection */ XCloseDisplay(dpy); DEBUGMSGT(("verbose:nvCtrlTable:nvCtrlTable_container_load", "inserted %d records\n", count)); return MFD_SUCCESS; } /* nvCtrlTable_container_load */
static void is_nvidia_plugin_activate(PeasActivatable *activatable) { IsNvidiaPlugin *self = IS_NVIDIA_PLUGIN(activatable); IsNvidiaPluginPrivate *priv = self->priv; Bool ret; int event_base, error_base; gint n; int i; /* search for sensors and add them to manager */ if (!priv->inited) { is_warning("nvidia", "not inited, unable to find sensors"); goto out; } is_debug("nvidia", "searching for sensors"); /* check if the NV-CONTROL extension is available on this X * server */ ret = XNVCTRLQueryExtension(priv->display, &event_base, &error_base); if (!ret) { goto out; } /* get number of GPUs, then for each GPU get any thermal_sensors and coolers used by it */ ret = XNVCTRLQueryTargetCount(priv->display, NV_CTRL_TARGET_TYPE_GPU, &n); if (!ret) { goto out; } for (i = 0; i < n; i++) { guint j; char *label = NULL; ret = XNVCTRLQueryTargetStringAttribute(priv->display, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_STRING_PRODUCT_NAME, &label); for (j = 0; j < G_N_ELEMENTS(map); j++) { int32_t *data; int len; int k; ret = XNVCTRLQueryTargetBinaryData(priv->display, NV_CTRL_TARGET_TYPE_GPU, i, 0, map[j].gpu_attribute, (unsigned char **)&data, &len); if (!ret) { continue; } /* data[0] contains number of sensors, and each sensor indice follows */ for (k = 1; k <= data[0]; k++) { int idx = data[k]; gint value; IsSensor *sensor; gchar *path; ret = XNVCTRLQueryTargetAttribute(priv->display, map[j].target, idx, 0, map[j].attribute, &value); if (!ret) { continue; } path = g_strdup_printf("nvidia/%s%d", map[j].description, idx); if (map[j].target == NV_CTRL_TARGET_TYPE_COOLER) { /* fan sensors are given as a percentage from 0 to 100 */ sensor = is_sensor_new(path); is_sensor_set_icon(sensor, IS_STOCK_FAN); is_sensor_set_units(sensor, "%"); is_sensor_set_low_value(sensor, 0.0); is_sensor_set_high_value(sensor, 100.0); } else { sensor = is_temperature_sensor_new(path); is_sensor_set_icon(sensor, IS_STOCK_GPU); } /* no decimal places to display */ is_sensor_set_digits(sensor, 0); is_sensor_set_label(sensor, label); /* connect to update-value signal */ g_signal_connect(sensor, "update-value", G_CALLBACK(update_sensor_value), self); is_manager_add_sensor(is_application_get_manager(priv->application), sensor); g_free(path); } free(data); } free(label); } out: return; }
int main(int argc, char *argv[]) { Display *dpy; Bool ret; int screen, major, minor, len, i, j; char *str, *start, *str0, *str1; int *enabledDpyIds; /* * Open a display connection, and make sure the NV-CONTROL X * extension is present on the screen we want to use. */ dpy = XOpenDisplay(NULL); if (!dpy) { fprintf(stderr, "Cannot open display '%s'.\n\n", XDisplayName(NULL)); return 1; } screen = GetNvXScreen(dpy); ret = XNVCTRLQueryVersion(dpy, &major, &minor); if (ret != True) { fprintf(stderr, "The NV-CONTROL X extension does not exist " "on '%s'.\n\n", XDisplayName(NULL)); return 1; } printf("\nUsing NV-CONTROL extension %d.%d on %s\n\n", major, minor, XDisplayName(NULL)); /* * query the enabled display devices on this X screen and print basic * information about each X screen. */ ret = XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN, (unsigned char **) &enabledDpyIds, &len); if (!ret || (len < sizeof(enabledDpyIds[0]))) { fprintf(stderr, "Failed to query the enabled Display Devices.\n\n"); return 1; } printf("Enabled Display Devices:\n"); for (i = 0; i < enabledDpyIds[0]; i++) { int dpyId = enabledDpyIds[i+1]; print_display_id_and_name(dpy, dpyId, " "); } printf("\n"); /* * perform the requested action, based on the specified * commandline option */ if (argc <= 1) goto printHelp; /* * for each enabled display device on this X screen, query the list of * modelines in the mode pool using NV_CTRL_BINARY_DATA_MODELINES, then * print the results. */ if (strcmp(argv[1], "--print-modelines") == 0) { for (i = 0; i < enabledDpyIds[0]; i++) { int dpyId = enabledDpyIds[i+1]; ret = XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_BINARY_DATA_MODELINES, (void *) &str, &len); if (!ret) { fprintf(stderr, "Failed to query ModeLines.\n\n"); return 1; } /* * the returned data is in the form: * * "ModeLine 1\0ModeLine 2\0ModeLine 3\0Last ModeLine\0\0" * * so walk from one "\0" to the next to print each ModeLine. */ printf("Modelines for DPY-%d:\n", dpyId); start = str; for (j = 0; j < len; j++) { if (str[j] == '\0') { printf(" %s\n", start); start = &str[j+1]; } } XFree(str); } } /* * for each enabled display device on this X screen, query the current * modeline using NV_CTRL_STRING_CURRENT_MODELINE. */ else if (strcmp(argv[1], "--print-current-modeline") == 0) { for (i = 0; i < enabledDpyIds[0]; i++) { int dpyId = enabledDpyIds[i+1]; ret = XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_STRING_CURRENT_MODELINE, &str); if (!ret) { fprintf(stderr, "Failed to query current ModeLine.\n\n"); return 1; } printf("Current Modeline for DPY-%d:\n", dpyId); printf(" %s\n\n", str); XFree(str); } } /* * add the specified modeline to the mode pool for the specified * display device, using NV_CTRL_STRING_ADD_MODELINE */ else if ((strcmp(argv[1], "--add-modeline") == 0) && argv[2] && argv[3]) { int dpyId = strtol(argv[2], NULL, 0); ret = XNVCTRLSetTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_STRING_ADD_MODELINE, argv[3]); if (!ret) { fprintf(stderr, "Failed to add the modeline \"%s\" to DPY-%d's " "mode pool.\n\n", argv[3], dpyId); return 1; } printf("Added modeline \"%s\" to DPY-%d's mode pool.\n\n", argv[3], dpyId); } /* * delete the specified modeline from the mode pool for the * specified display device, using NV_CTRL_STRING_DELETE_MODELINE */ else if ((strcmp(argv[1], "--delete-modeline") == 0) && argv[2] && argv[3]) { int dpyId = strtol(argv[2], NULL, 0); ret = XNVCTRLSetTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_STRING_DELETE_MODELINE, argv[3]); if (!ret) { fprintf(stderr, "Failed to delete the mode \"%s\" from DPY-%d's " "mode pool.\n\n", argv[3], dpyId); return 1; } printf("Deleted modeline \"%s\" from DPY-%d's mode pool.\n\n", argv[3], dpyId); } /* * generate a GTF modeline using NV_CTRL_STRING_OPERATION_GTF_MODELINE */ else if ((strcmp(argv[1], "--generate-gtf-modeline") == 0) && argv[2] && argv[3] && argv[4]) { char pGtfString[128]; char *pOut; snprintf(pGtfString, 128, "width=%s, height=%s, refreshrate=%s", argv[2], argv[3], argv[4]); ret = XNVCTRLStringOperation(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_STRING_OPERATION_GTF_MODELINE, pGtfString, &pOut); if (!ret) { fprintf(stderr, "Failed to generate GTF ModeLine from " "\"%s\".\n\n", pGtfString); return 1; } printf("GTF ModeLine from \"%s\": %s\n\n", pGtfString, pOut); } /* * generate a CVT modeline using NV_CTRL_STRING_OPERATION_CVT_MODELINE */ else if ((strcmp(argv[1], "--generate-cvt-modeline") == 0) && argv[2] && argv[3] && argv[4] && argv[5]) { char pCvtString[128]; char *pOut; snprintf(pCvtString, 128, "width=%s, height=%s, refreshrate=%s, " "reduced-blanking=%s", argv[2], argv[3], argv[4], argv[5]); ret = XNVCTRLStringOperation(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_STRING_OPERATION_CVT_MODELINE, pCvtString, &pOut); if (!ret) { fprintf(stderr, "Failed to generate CVT ModeLine from " "\"%s\".\n\n", pCvtString); return 1; } printf("CVT ModeLine from \"%s\": %s\n\n", pCvtString, pOut); } /* * query the MetaModes for the X screen, using * NV_CTRL_BINARY_DATA_METAMODES. */ else if (strcmp(argv[1], "--print-metamodes") == 0) { /* get list of metamodes */ ret = XNVCTRLQueryBinaryData(dpy, screen, 0, // n/a NV_CTRL_BINARY_DATA_METAMODES, (void *) &str, &len); if (!ret) { fprintf(stderr, "Failed to query MetaModes.\n\n"); return 1; } /* * the returned data is in the form: * * "MetaMode 1\0MetaMode 2\0MetaMode 3\0Last MetaMode\0\0" * * so walk from one "\0" to the next to print each MetaMode. */ printf("MetaModes:\n"); start = str; for (j = 0; j < len; j++) { if (str[j] == '\0') { printf(" %s\n", start); start = &str[j+1]; } } XFree(str); } /* * query the MetaModes for the X screen, using * NV_CTRL_BINARY_DATA_METAMODES_VERSION_2. */ else if (strcmp(argv[1], "--print-metamodes-version2") == 0) { /* get list of metamodes */ ret = XNVCTRLQueryBinaryData(dpy, screen, 0, // n/a NV_CTRL_BINARY_DATA_METAMODES_VERSION_2, (void *) &str, &len); if (!ret) { fprintf(stderr, "Failed to query MetaModes.\n\n"); return 1; } /* * the returned data is in the form: * * "MetaMode 1\0MetaMode 2\0MetaMode 3\0Last MetaMode\0\0" * * so walk from one "\0" to the next to print each MetaMode. */ printf("MetaModes:\n"); start = str; for (j = 0; j < len; j++) { if (str[j] == '\0') { printf(" %s\n", start); start = &str[j+1]; } } XFree(str); } /* * query the currently in use MetaMode. Note that an alternative * way to accomplish this is to use XRandR to query the current * mode's refresh rate, and then match the refresh rate to the id * reported in the returned NV_CTRL_BINARY_DATA_METAMODES data. */ else if (strcmp(argv[1], "--print-current-metamode") == 0) { ret = XNVCTRLQueryStringAttribute(dpy, screen, 0, NV_CTRL_STRING_CURRENT_METAMODE, &str); if (!ret) { fprintf(stderr, "Failed to query the current MetaMode.\n\n"); return 1; } printf("current metamode: \"%s\"\n\n", str); XFree(str); } /* * query the currently in use MetaMode. Note that an alternative * way to accomplish this is to use XRandR to query the current * mode's refresh rate, and then match the refresh rate to the id * reported in the returned NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 data. */ else if (strcmp(argv[1], "--print-current-metamode-version2") == 0) { ret = XNVCTRLQueryStringAttribute(dpy, screen, 0, NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2, &str); if (!ret) { fprintf(stderr, "Failed to query the current MetaMode.\n\n"); return 1; } printf("current metamode: \"%s\"\n\n", str); XFree(str); } /* * add the given MetaMode to X screen's list of MetaModes, using * NV_CTRL_STRING_OPERATION_ADD_METAMODE; example MetaMode string: * * "nvidia-auto-select, nvidia-auto-select" * * The output string will contain "id=#" which indicates the * unique identifier for this MetaMode. You can then use XRandR * to switch to this mode by matching the identifier with the * refresh rate reported via XRandR. * * For example: * * $ ./nv-control-dpy --add-metamode \ * "nvidia-auto-select, nvidia-auto-select" * * Using NV-CONTROL extension 1.12 on :0 * Enabled Display Devices: * DPY-0 : EIZO F931 * DPY-1 : ViewSonic P815-4 * * Added MetaMode "nvidia-auto-select, nvidia-auto-select"; * pOut: "id=52" * * $ xrandr -q * SZ: Pixels Physical Refresh * 0 3200 x 1200 ( 821mm x 302mm ) 51 52 * *1 1600 x 600 ( 821mm x 302mm ) *50 * Current rotation - normal * Current reflection - none * Rotations possible - normal * Reflections possible - none * * $ xrandr -s 0 -r 52 */ else if ((strcmp(argv[1], "--add-metamode") == 0) && (argv[2])) { char *pOut; ret = XNVCTRLStringOperation(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_STRING_OPERATION_ADD_METAMODE, argv[2], &pOut); if (!ret) { fprintf(stderr, "Failed to add the MetaMode \"%s\".\n\n", argv[2]); return 1; } printf("Added MetaMode \"%s\"; pOut: \"%s\"\n\n", argv[2], pOut); XFree(pOut); } /* * delete the given MetaMode from the X screen's list of * MetaModes, using NV_CTRL_STRING_DELETE_METAMODE */ else if ((strcmp(argv[1], "--delete-metamode") == 0) && (argv[1])) { ret = XNVCTRLSetStringAttribute(dpy, screen, 0, NV_CTRL_STRING_DELETE_METAMODE, argv[2]); if (!ret) { fprintf(stderr, "Failed to delete the MetaMode.\n\n"); return 1; } printf("Deleted MetaMode \"%s\".\n\n", argv[2]); } /* * query the valid frequency ranges for each display device, using * NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES and * NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES */ else if (strcmp(argv[1], "--get-valid-freq-ranges") == 0) { for (i = 0; i < enabledDpyIds[0]; i++) { int dpyId = enabledDpyIds[i+1]; ret = XNVCTRLQueryTargetStringAttribute (dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES, &str0); if (!ret) { fprintf(stderr, "Failed to query HorizSync for DPY-%d.\n\n", dpyId); return 1; } ret = XNVCTRLQueryTargetStringAttribute (dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES, &str1); if (!ret) { fprintf(stderr, "Failed to query VertRefresh for DPY-%d.\n\n", dpyId); XFree(str0); return 1; } printf("frequency information for DPY-%d:\n", dpyId); printf(" HorizSync : \"%s\"\n", str0); printf(" VertRefresh : \"%s\"\n\n", str1); XFree(str0); XFree(str1); } } /* * attempt to build the modepool for each display device; this * will fail for any display device that already has a modepool */ else if (strcmp(argv[1], "--build-modepool") == 0) { for (i = 0; i < enabledDpyIds[0]; i++) { int dpyId = enabledDpyIds[i+1]; ret = XNVCTRLStringOperation (dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL, argv[2], &str0); if (!ret) { fprintf(stderr, "Failed to build modepool for DPY-%d (it most " "likely already has a modepool).\n\n", dpyId); } else { printf("Built modepool for DPY-%d.\n\n", dpyId); } } } /* * query the assigned display devices on this X screen; these are the * display devices that are available to the X screen for use by MetaModes. */ else if (strcmp(argv[1], "--get-assigned-dpys") == 0) { int *pData = NULL; int len; ret = XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN, (unsigned char **) &pData, &len); if (!ret || (len < sizeof(pData[0]))) { fprintf(stderr, "failed to query the assigned display " "devices.\n\n"); return 1; } printf("Assigned display devices:\n"); for (i = 0; i < pData[0]; i++) { int dpyId = pData[i+1]; printf(" DPY-%d\n", dpyId); } printf("\n"); XFree(pData); } /* * query information about the GPUs in the system */ else if (strcmp(argv[1], "--query-gpus") == 0) { int num_gpus, num_screens, i; int *pData; printf("GPU Information:\n"); /* Get the number of gpus in the system */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_GPU, &num_gpus); if (!ret) { fprintf(stderr, "Failed to query number of gpus.\n\n"); return 1; } printf(" number of GPUs: %d\n", num_gpus); /* List the X screen number of all X screens driven by each gpu */ for (i = 0; i < num_gpus; i++) { ret = XNVCTRLQueryTargetBinaryData (dpy, NV_CTRL_TARGET_TYPE_GPU, i, // target_id 0, NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU, (unsigned char **) &pData, &len); if (!ret || (len < sizeof(pData[0]))) { fprintf(stderr, "Failed to query list of X Screens\n"); return 1; } printf(" number of X screens using GPU %d: %d\n", i, pData[0]); /* List X Screen number of all X Screens driven by this GPU. */ printf(" Indices of X screens using GPU %d: ", i); for (j = 1; j <= pData[0]; j++) { printf(" %d", pData[j]); } printf("\n"); XFree(pData); } /* Get the number of X Screens in the system * * NOTE: If Xinerama is enabled, ScreenCount(dpy) will return 1, * where as querying the screen count information from * NV-CONTROL will return the number of underlying X Screens. */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, &num_screens); if (!ret) { fprintf(stderr, "Failed to query number of X Screens\n\n"); return 1; } printf("\n"); printf(" number of X screens (ScreenCount): %d\n", ScreenCount(dpy)); printf(" number of X screens (NV-CONTROL): %d\n\n", num_screens); for (i = 0; i < num_screens; i++) { ret = XNVCTRLQueryTargetBinaryData (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, i, // target_id 0, NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, (unsigned char **) &pData, &len); if (!ret || (len < sizeof(pData[0]))) { fprintf(stderr, "Failed to query list of gpus\n\n"); return 1; } printf(" number of GPUs used by X screen %d: %d\n", i, pData[0]); /* List gpu number of all gpus driven by this X screen */ printf(" Indices of GPUs used by X screen %d: ", i); for (j = 1; j <= pData[0]; j++) { printf(" %d", pData[j]); } printf("\n"); XFree(pData); } printf("\n"); } /* * probe for any newly connected display devices */ else if (strcmp(argv[1], "--probe-dpys") == 0) { int num_gpus, i; printf("Display Device Probed Information:\n\n"); /* Get the number of gpus in the system */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_GPU, &num_gpus); if (!ret) { fprintf(stderr, "Failed to query number of gpus\n\n"); return 1; } printf(" number of GPUs: %d\n", num_gpus); /* Probe and list the Display devices */ for (i = 0; i < num_gpus; i++) { int deprecated; int *pData; /* Get the gpu name */ ret = XNVCTRLQueryTargetStringAttribute (dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_STRING_PRODUCT_NAME, &str); if (!ret) { fprintf(stderr, "Failed to query gpu name\n\n"); return 1; } /* Probe the GPU for new/old display devices */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_PROBE_DISPLAYS, &deprecated); if (!ret) { fprintf(stderr, "Failed to probe the enabled Display " "Devices on GPU-%d (%s).\n\n", i, str); return 1; } printf(" display devices on GPU-%d (%s):\n", i, str); XFree(str); /* Report results */ ret = XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU, (unsigned char **) &pData, &len); if (!ret || (len < sizeof(pData[0]))) { fprintf(stderr, "Failed to query the connected Display Devices.\n\n"); return 1; } for (j = 0; j < pData[0]; j++) { int dpyId = pData[j+1]; print_display_id_and_name(dpy, dpyId, " "); } printf("\n"); } printf("\n"); } /* * query the nvidiaXineramaInfoOrder */ else if (strcmp(argv[1], "--query-nvidia-xinerama-info-order") == 0) { ret = XNVCTRLQueryTargetStringAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER, &str); if (!ret) { fprintf(stderr, "Failed to query nvidiaXineramaInfoOrder.\n\n"); return 1; } printf("nvidiaXineramaInfoOrder: %s\n\n", str); } /* * assign the nvidiaXineramaInfoOrder */ else if ((strcmp(argv[1], "--assign-nvidia-xinerama-info-order")== 0) && argv[2]) { ret = XNVCTRLSetStringAttribute (dpy, screen, 0, NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER, argv[2]); if (!ret) { fprintf(stderr, "Failed to assign " "nvidiaXineramaInfoOrder = \"%s\".\n\n", argv[2]); return 1; } printf("assigned nvidiaXineramaInfoOrder: \"%s\"\n\n", argv[2]); } /* * use NV_CTRL_MAX_SCREEN_WIDTH and NV_CTRL_MAX_SCREEN_HEIGHT to * query the maximum screen dimensions on each GPU in the system */ else if (strcmp(argv[1], "--max-screen-size") == 0) { int num_gpus, i, width, height; /* Get the number of gpus in the system */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_GPU, &num_gpus); if (!ret) { fprintf(stderr, "Failed to query number of gpus.\n\n"); return 1; } for (i = 0; i < num_gpus; i++) { ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_MAX_SCREEN_WIDTH, &width); if (!ret) { fprintf(stderr, "Failed to query the maximum screen " "width on GPU-%d\n\n", i); return 1; } ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_MAX_SCREEN_HEIGHT, &height); if (!ret) { fprintf(stderr, "Failed to query the maximum screen " "height on GPU-%d.\n\n", i); return 1; } printf("GPU-%d: maximum X screen size: %d x %d.\n\n", i, width, height); } } /* * demonstrate how to use NV-CONTROL to query what modelines are * used by the MetaModes of the X screen: we first query all the * MetaModes, parse out the display device names and mode names, * and then lookup the modelines associated with those mode names * on those display devices * * this could be implemented much more efficiently, but * demonstrates the general idea */ else if (strcmp(argv[1], "--print-used-modelines") == 0) { char *pMetaModes, *pModeLines[8], *tmp, *modeString; char *modeLine, *modeName, *noWhiteSpace; int MetaModeLen, ModeLineLen[8], ModeLineDpyId[8]; int dpyId; /* first, we query the MetaModes on this X screen */ XNVCTRLQueryBinaryData(dpy, screen, 0, NV_CTRL_BINARY_DATA_METAMODES_VERSION_2, (void *) &pMetaModes, &MetaModeLen); /* * then, we query the ModeLines for each display device on * this X screen; we'll need these later */ for (i = 0; i < enabledDpyIds[0]; i++) { dpyId = enabledDpyIds[i+1]; XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_DISPLAY, dpyId, 0, NV_CTRL_BINARY_DATA_MODELINES, (void *) &str, &len); pModeLines[i] = str; ModeLineLen[i] = len; ModeLineDpyId[i] = dpyId; } /* now, parse each MetaMode */ str = start = pMetaModes; for (j = 0; j < MetaModeLen - 1; j++) { /* * if we found the end of a line, treat the string from * start to str[j] as a MetaMode */ if ((str[j] == '\0') && (str[j+1] != '\0')) { printf("MetaMode: %s\n", start); /* * remove any white space from the string to make * parsing easier */ noWhiteSpace = remove_whitespace(start); /* * the MetaMode may be preceded with "token=value" * pairs, separated by the main MetaMode with "::"; if * "::" exists in the string, skip past it */ tmp = strstr(noWhiteSpace, "::"); if (tmp) { tmp += 2; } else { tmp = noWhiteSpace; } /* Parse each mode from the metamode */ for (modeString = mode_strtok(tmp); modeString; modeString = mode_strtok(NULL)) { /* * retrieve the modeName and display device id * for this segment of the Metamode */ if (!parse_mode_string(modeString, &modeName, &dpyId)) { fprintf(stderr, " Failed to parse mode string '%s'." "\n\n", modeString); continue; } /* lookup the modeline that matches */ for (i = 0; i < enabledDpyIds[0]; i++) { if (ModeLineDpyId[i] == dpyId) { break; } } if ( i >= enabledDpyIds[0] ) { fprintf(stderr, " Failed to find modelines for " "DPY-%d.\n\n", dpyId); continue; } modeLine = find_modeline(modeName, pModeLines[i], ModeLineLen[i]); printf(" DPY-%d: %s\n", dpyId, modeLine); } printf("\n"); free(noWhiteSpace); /* move to the next MetaMode */ start = &str[j+1]; } } } /* Display all names each display device goes by */ else if (strcmp(argv[1], "--print-display-names") == 0) { int *pData; int len, i; printf("Display Device Information:\n"); ret = XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_GPU, 0, 0, NV_CTRL_BINARY_DATA_DISPLAY_TARGETS, (unsigned char **) &pData, &len); if (!ret || (len < sizeof(pData[0]))) { fprintf(stderr, "Failed to query number of display devices.\n\n"); return 1; } printf(" number of display devices: %d\n", pData[0]); for (i = 1; i <= pData[0]; i++) { printf("\n Display Device: %d\n", pData[i]); print_display_name(dpy, pData[i], NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME, "Type Basename"); print_display_name(dpy, pData[i], NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID, "Type ID"); print_display_name(dpy, pData[i], NV_CTRL_STRING_DISPLAY_NAME_DP_GUID, "DP GUID"); print_display_name(dpy, pData[i], NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH, "EDID HASH"); print_display_name(dpy, pData[i], NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX, "Target Index"); print_display_name(dpy, pData[i], NV_CTRL_STRING_DISPLAY_NAME_RANDR, "RANDR"); } } /* * print help information */ else { printHelp: printf("\nnv-control-dpy [options]:\n\n"); printf(" ModeLine options:\n\n"); printf(" --print-modelines: print the modelines in the mode pool " "for each Display Device.\n\n"); printf(" --print-current-modeline: print the current modeline " "for each Display Device.\n\n"); printf(" --add-modeline [dpy id] [modeline]: " "add new modeline.\n\n"); printf(" --delete-modeline [dpy id] [modename]: " "delete modeline with modename.\n\n"); printf(" --generate-gtf-modeline [width] [height] [refreshrate]:" " use the GTF formula" " to generate a modeline for the specified parameters.\n\n"); printf(" --generate-cvt-modeline [width] [height] [refreshrate]" " [reduced-blanking]: use the CVT formula" " to generate a modeline for the specified parameters.\n\n"); printf(" MetaMode options:\n\n"); printf(" --print-metamodes: print the current MetaModes for the " "X screen\n\n"); printf(" --print-metamodes-version2: print the current MetaModes for " "the X screen with extended information\n\n"); printf(" --add-metamode [metamode]: add the specified " "MetaMode to the X screen's list of MetaModes.\n\n"); printf(" --delete-metamode [metamode]: delete the specified MetaMode " "from the X screen's list of MetaModes.\n\n"); printf(" --print-current-metamode: print the current MetaMode.\n\n"); printf(" --print-current-metamode-version2: print the current " "MetaMode with extended information.\n\n"); printf(" Misc options:\n\n"); printf(" --get-valid-freq-ranges: query the valid frequency " "information for each display device.\n\n"); printf(" --build-modepool: build a modepool for any display device " "that does not already have one.\n\n"); printf(" --get-assigned-dpys: query the assigned display device for " "this X screen\n\n"); printf(" --query-gpus: print GPU information and relationship to " "X screens.\n\n"); printf(" --probe-dpys: probe GPUs for new display devices\n\n"); printf(" --query-nvidia-xinerama-info-order: query the " "nvidiaXineramaInfoOrder.\n\n"); printf(" --assign-nvidia-xinerama-info-order [order]: assign the " "nvidiaXineramaInfoOrder.\n\n"); printf(" --max-screen-size: query the maximum screen size " "on all GPUs in the system\n\n"); printf(" --print-used-modelines: print the modeline for each display " "device for each MetaMode on the X screen.\n\n"); printf(" --print-display-names: print all the names associated with " "each display device on the server\n\n"); } return 0; }
/* * do_query() * * Prints information for all frame lock (g-sync) devices found on * the given X server. * */ static void do_query(Display *dpy) { Bool ret; int num_framelocks; int framelock; int gpu; int mask; char *name; int *data; int len; int i; int enabled; /* Query the number of frame lock devices on the server */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK, &num_framelocks); if (!ret) { printf("Failed to query number of frame lock devices!\n"); return; } printf("Found %d frame lock device(s) on server.\n", num_framelocks); if ( !num_framelocks ) { return; } /* Display information for all frame lock devices found */ for (framelock = 0; framelock < num_framelocks; framelock++) { printf("\n"); printf("- Frame Lock Board %d :\n", framelock); /* Query the GPUs connected to this frame lock device */ ret = XNVCTRLQueryTargetBinaryData (dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK, framelock, // target_id 0, // display_mask NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK, (unsigned char **) &data, &len); if (!ret) { printf(" - Failed to query list of GPUs!\n"); continue; } /* Display information for all GPUs connected to frame lock device */ if ( !data[0] ) { printf(" - No GPUs found!\n"); } else { printf(" - Found %d GPU(s).\n", data[0]); } for (i = 1; i <= data[0]; i++) { gpu = data[i]; /* Query GPU product name */ ret = XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_STRING_PRODUCT_NAME, &name); if (!ret) { printf(" - Failed to query GPU %d product name.\n", gpu); continue; } printf(" - GPU %d (%s) :\n", gpu, name); /* Query GPU sync state */ printf(" - Sync : "); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_SYNC, &enabled); if (!ret) { printf("Failed to query sync state.\n"); } else { printf("%sabled\n", enabled ? "En" : "Dis"); } /* Query GPU displays */ printf(" - Displays Mask : "); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_ENABLED_DISPLAYS, &mask); if (!ret) { printf("Failed to query enabled displays.\n"); } else { printf("0x%08x\n", mask); } /* Query GPU server (master) */ printf(" - Server Mask : "); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_MASTER, &mask); if (!ret) { printf("Failed to query server mask.\n"); } else { printf("0x%08x\n", mask); } /* Query GPU clients (slaves) */ printf(" - Clients Mask : "); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_SLAVES, &mask); if (!ret) { printf("Failed to query clients mask.\n"); } else { printf("0x%08x\n", mask); } } /* Done disabling GPUs */ XFree(data); } /* Done disabling Frame Lock Devices */ } /* do_query() */
int main(int argc, char *argv[]) { Display *dpy; Bool ret; int screen, display_devices, mask, major, minor; char *str; int nDisplayDevice; /* * Open a display connection, and make sure the NV-CONTROL X * extension is present on the screen we want to use. */ dpy = XOpenDisplay(NULL); if (!dpy) { fprintf(stderr, "Cannot open display '%s'.\n\n", XDisplayName(NULL)); return 1; } screen = GetNvXScreen(dpy); ret = XNVCTRLQueryVersion(dpy, &major, &minor); if (ret != True) { fprintf(stderr, "The NV-CONTROL X extension does not exist on '%s'.\n\n", XDisplayName(NULL)); return 1; } /* * query the connected display devices on this X screen and print * basic information about each X screen */ ret = XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_CONNECTED_DISPLAYS, &display_devices); if (!ret) { fprintf(stderr, "Failed to query the enabled Display Devices.\n\n"); return 1; } int pci_bus; int pci_device; int pci_func; ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, 0 /* Just query first GPU */, 0, NV_CTRL_PCI_BUS, &pci_bus); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, 0 /* Just query first GPU */, 0, NV_CTRL_PCI_DEVICE, &pci_device); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, 0 /* Just query first GPU */, 0, NV_CTRL_PCI_FUNCTION, &pci_func); dbset("system.hardware.nvidia.busid=%i:%i:%i", pci_bus, pci_device, pci_func); nDisplayDevice = 0; for (mask = 1; mask < (1 << 24); mask <<= 1) { if (display_devices & mask) { XNVCTRLQueryStringAttribute(dpy, screen, mask, NV_CTRL_STRING_DISPLAY_DEVICE_NAME, &str); dbset("system.x11.display.%i.device=%s" , nDisplayDevice, display_device_name(mask)); dbset("system.x11.display.%i.mode.0=nvidia-auto-select", nDisplayDevice); dbset("system.x11.display.%i.default=nvidia-auto-select", nDisplayDevice); printf("%i:%s:0x%08x:%s\n", nDisplayDevice, display_device_name(mask), mask, str); nDisplayDevice++; } } if (nDisplayDevice > 1) { // more than one screen found dbset("system.x11.dualhead.enabled=1"); } else { dbset("system.x11.dualhead.enabled=0"); } char *dummy; for (; nDisplayDevice <= 3; nDisplayDevice++) { if (asprintf(&dummy, "system.x11.display.%i", nDisplayDevice) >= 0) { dbremove(dummy); free(dummy); } } return 0; }
/* creates the connection to the X server and checks whether the * NV-CONTROL extension is loaded */ static GList *nvidia_plugin_init(void) { int dummy; int event_base, error_base; GList *sensors = NULL; /* create the connection to the X server */ if (!(nvidia_sensors_dpy = XOpenDisplay(NULL))) { /* no connection to the X server avaible */ return sensors; } /* check if the NV-CONTROL extension is available on this X * server - if so add the two sensors if they exist */ if (XNVCTRLQueryExtension(nvidia_sensors_dpy, &event_base, &error_base)) { int i, cnt; if (XNVCTRLQueryTargetCount(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_THERMAL_SENSOR, &cnt)) { for (i = 0; i < cnt; i++) { gchar *id = g_strdup_printf("GPU%d%s", i, THERMAL_SENSOR_TEMP); sensors_applet_plugin_add_sensor(&sensors, THERMAL_SENSOR_TEMP, id, _("GPU"), TEMP_SENSOR, TRUE, GPU_ICON, DEFAULT_GRAPH_COLOR); g_free(id); } } if (XNVCTRLQueryTargetCount(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_COOLER, &cnt)) { for (i = 0; i < cnt; i++) { gchar *id = g_strdup_printf("GPU%d%s", i, THERMAL_COOLER_LEVEL); sensors_applet_plugin_add_sensor(&sensors, THERMAL_COOLER_LEVEL, id, _("GPU"), FAN_SENSOR, TRUE, FAN_ICON, DEFAULT_GRAPH_COLOR); g_free(id); } } if (XNVCTRLQueryTargetCount(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_GPU, &cnt)) { for (i = 0; i < cnt; i++) { if (XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_GPU_CORE_TEMPERATURE, &dummy)) { gchar *id = g_strdup_printf("GPU%d%s", i, GPU_CORE_TEMP); sensors_applet_plugin_add_sensor(&sensors, GPU_CORE_TEMP, id, _("GPU"), TEMP_SENSOR, TRUE, GPU_ICON, DEFAULT_GRAPH_COLOR); g_free(id); } if (XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy, NV_CTRL_TARGET_TYPE_GPU, i, 0, NV_CTRL_AMBIENT_TEMPERATURE, &dummy)) { gchar *id = g_strdup_printf("GPU%d%s", i, AMBIENT_TEMP); sensors_applet_plugin_add_sensor(&sensors, AMBIENT_TEMP, id, _("Ambient"), TEMP_SENSOR, FALSE, GENERIC_ICON, DEFAULT_GRAPH_COLOR); g_free(id); } } } } return sensors; }
static int hwloc_gl_discover(struct hwloc_backend *backend) { struct hwloc_topology *topology = backend->topology; unsigned i, res = 0; int err; if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) return 0; if (!hwloc_topology_is_thissystem(topology)) { hwloc_debug("%s", "\nno GL detection (not thissystem)\n"); return 0; } for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) { Display* display; char displayName[10]; int opcode, event, error; unsigned j; /* open X server */ snprintf(displayName, sizeof(displayName), ":%u", i); display = XOpenDisplay(displayName); if (!display) continue; /* Check for NV-CONTROL extension (it's per server) */ if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) { XCloseDisplay(display); continue; } for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) { hwloc_obj_t osdev, parent; const int screen = j; unsigned int *ptr_binary_data; int data_length; int gpu_number; int nv_ctrl_pci_bus; int nv_ctrl_pci_device; int nv_ctrl_pci_domain; int nv_ctrl_pci_func; char *productname; char name[64]; /* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */ if (!XNVCTRLIsNvScreen(display, screen)) continue; /* Gets the GPU number attached to the default screen. */ /* For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, (unsigned char **) &ptr_binary_data, &data_length); if (!err) continue; gpu_number = ptr_binary_data[1]; free(ptr_binary_data); #ifdef NV_CTRL_PCI_DOMAIN /* Gets the ID's of the GPU defined by gpu_number * For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain); if (!err) continue; #else nv_ctrl_pci_domain = 0; #endif err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func); if (!err) continue; productname = NULL; err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_STRING_PRODUCT_NAME, &productname); snprintf(name, sizeof(name), ":%u.%u", i, j); osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); osdev->name = strdup(name); osdev->logical_index = -1; osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU; hwloc_obj_add_info(osdev, "Backend", "GL"); hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation"); if (productname) hwloc_obj_add_info(osdev, "GPUModel", productname); parent = hwloc_pci_belowroot_find_by_busid(topology, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); if (!parent) parent = hwloc_pci_find_busid_parent(topology, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); if (!parent) parent = hwloc_get_root_obj(topology); hwloc_insert_object_by_parent(topology, parent, osdev); hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", name, productname, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); res++; } XCloseDisplay(display); } return res; }
// List the configuration space of the GVI device. void do_listconfig(Display *dpy, int gvi) { NVCTRLAttributeValidValuesRec values; unsigned int fmts[3]; int i; char *pOut = NULL; Bool ret; // Assume GVI device has been configured already. if (gvi < 0) { gvi = 0; } printf("Querying Valid Configuring Space of GVI device %d:\n\n", gvi); /* Query stream (link to jack+channel) topology */ ret = XNVCTRLStringOperation(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, // target_id 0, // display_mask NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS, NULL, // pIn &pOut); if (!ret || !pOut) { printf(" - Failed to query stream topology configuration of " "GVI %d.\n", gvi); return; } printf("- Current Topology:\n\n"); printf(" %s\n\n", pOut ? pOut : "No streams are configured."); XFree(pOut); pOut = NULL; ret = XNVCTRLQueryValidTargetAttributeValues(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // display_mask NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, &values); if (!ret) { printf("- Failed to query valid video format values(1) of " "GVI %d.\n", gvi); return; } fmts[0] = values.u.bits.ints; ret = XNVCTRLQueryValidTargetAttributeValues(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // display_mask NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2, &values); if (!ret) { printf("- Failed to query valid video format values(2) of " "GVI %d.\n", gvi); return; } fmts[1] = values.u.bits.ints; ret = XNVCTRLQueryValidTargetAttributeValues(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // display_mask NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3, &values); if (!ret) { printf("- Failed to query valid video format values(3) of " "GVI %d.\n", gvi); return; } fmts[2] = values.u.bits.ints; printf("- Valid Formats (NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT): %08x\n", fmts[0]); printf("- Valid Formats (NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2): %08x\n", fmts[1]); printf("- Valid Formats (NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3): %08x\n", fmts[2]); printf("\n"); for (i = 0; i < 3; i++) { unsigned int fmt_list = fmts[i]; unsigned int fmt_bit; unsigned int fmt; unsigned int fmt_flags; unsigned int bpcs; unsigned int bpc_bit; unsigned int bpc; unsigned int samplings; unsigned int smp_bit; unsigned int sampling; while (fmt_list) { fmt_bit = firstbit(fmt_list); fmt_list &= (~fmt_bit); fmt = ffs(fmt_bit) - 1 + (32*i); printf("\n%s", VideoFormatName(fmt)); ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, fmt, // display_mask NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS, (int *)&fmt_flags); if (!ret) { printf(" - Failed to query flag bits for video format for " "GVI %d.\n", gvi); } else if (fmt_flags == NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_NONE) { printf(" (No flags set): \n"); } else { printf(" (Flags:"); printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_INTERLACED) ? 'I' : '_'); printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PROGRESSIVE) ? 'P' : '_'); printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PSF) ? 'F' : '_'); printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A) ? 'A' : '_'); printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B) ? 'B' : '_'); printf("%c", (fmt_flags & NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC) ? 'N' : '_'); printf("):\n"); } // Set the video format XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // display_mask NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT, fmt); // Get all bits per component (on first jack/channel) ret = XNVCTRLQueryValidTargetAttributeValues(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // jack 0, channel 0 NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT, &values); if (!ret) { printf(" - Failed to query valid bits per component " "of GVI %d.\n", gvi); continue; } bpcs = values.u.bits.ints; while (bpcs) { bpc_bit = firstbit(bpcs); bpcs &= (~bpc_bit); bpc = ffs(bpc_bit) -1; printf(" %s:\n", BPCName(bpc)); // Set the bits per component XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // jack 0, channel 0 NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT, bpc); // Get all component samplings (on first jack/channel) ret = XNVCTRLQueryValidTargetAttributeValues(dpy, NV_CTRL_TARGET_TYPE_GVI, gvi, 0, // display_mask NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING, &values); if (!ret) { printf(" - Failed to query valid component sampling " "values of GVI %d.\n", gvi); continue; } samplings = values.u.bits.ints; while (samplings) { smp_bit = firstbit(samplings); samplings &= (~smp_bit); sampling = ffs(smp_bit) -1; printf(" %s\n", SamplingName(sampling)); } // All component samplings } // Add BPC } // All formats } // All format lists } /* do_listconfig() */
static void hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data) { int err; unsigned i,j; /* mark the number of display as 0 in case we fail below, * so that we don't try again later. */ data->nr_display = 0; for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) { Display* display; char displayName[10]; int opcode, event, error; /* open X server */ snprintf(displayName, sizeof(displayName), ":%u", i); display = XOpenDisplay(displayName); if (!display) continue; /* Check for NV-CONTROL extension (it's per server) */ if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) { XCloseDisplay(display); continue; } for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) { struct hwloc_gl_display_info_s *info = &data->display[data->nr_display]; const int screen = j; unsigned int *ptr_binary_data; int data_length; int gpu_number; int nv_ctrl_pci_bus; int nv_ctrl_pci_device; int nv_ctrl_pci_domain; int nv_ctrl_pci_func; char *productname; /* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */ if (!XNVCTRLIsNvScreen(display, screen)) continue; /* Gets the GPU number attached to the default screen. */ /* For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, (unsigned char **) &ptr_binary_data, &data_length); if (!err) continue; gpu_number = ptr_binary_data[1]; free(ptr_binary_data); #ifdef NV_CTRL_PCI_DOMAIN /* Gets the ID's of the GPU defined by gpu_number * For further details, see the <NVCtrl/NVCtrlLib.h> */ err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain); if (!err) continue; #else nv_ctrl_pci_domain = 0; #endif err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device); if (!err) continue; err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func); if (!err) continue; productname = NULL; err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, NV_CTRL_STRING_PRODUCT_NAME, &productname); snprintf(info->name, sizeof(info->name), ":%u.%u", i, j); info->port = i; info->device = j; info->pcidomain = nv_ctrl_pci_domain; info->pcibus = nv_ctrl_pci_bus; info->pcidevice = nv_ctrl_pci_device; info->pcifunc = nv_ctrl_pci_func; info->productname = productname; hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", info->name, productname, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); /* validate this device */ data->nr_display++; } XCloseDisplay(display); } }
/* * do_enable() * * Enables frame lock on the X Server by setting the first capable/available * display device as the frame lock server (master) and setting all other * display devices as clients (slaves). * * NOTE: It is up to the user to ensure that each display device is set with * the same refresh rate (mode timings). * */ static void do_enable(Display *dpy) { Bool ret; int num_framelocks; int framelock; int gpu; unsigned int mask; int *data; int len; int i; int enabled; int masterable; int pick_server = 1; int server_set = 0; /* Query the number of frame lock devices to enable */ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK, &num_framelocks); if (!ret) { printf("Failed to query number of frame lock devices!\n"); return; } printf("Found %d frame lock device(s) on server.\n", num_framelocks); if ( !num_framelocks ) { return; } /* Enable frame lock on all GPUs connected to each frame lock device */ for (framelock = 0; framelock < num_framelocks; framelock++) { printf("\n"); printf("- Frame Lock Board %d :\n", framelock); /* Query the GPUs connected to this frame lock device */ ret = XNVCTRLQueryTargetBinaryData (dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK, framelock, // target_id 0, // display_mask NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK, (unsigned char **) &data, &len); if (!ret) { printf(" - Failed to query list of GPUs!\n"); continue; } /* Enable frame lock on all GPUs connected to the frame lock device */ if ( !data[0] ) { printf(" - No GPUs found!\n"); } else { printf(" - Found %d GPU(s).\n", data[0]); } for (i = 1; i <= data[0]; i++) { gpu = data[i]; printf(" - Enabling G-Sync Device %d - GPU %d... ", framelock, gpu); /* Make sure frame lock is disabled */ XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_SYNC, &enabled); if (enabled != NV_CTRL_FRAMELOCK_SYNC_DISABLE) { printf("Frame lock already enabled!\n"); continue; } /* Get the list of displays to enable */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_ENABLED_DISPLAYS, (int *)&mask); if (!ret) { printf("Failed to query enabled displays!\n"); continue; } /* Query if any of the enabled displays can be set as a * master on this GPU. */ ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id mask, // display_mask NV_CTRL_FRAMELOCK_MASTERABLE, &masterable); if (!ret) { printf("Failed to query masterable!\n"); continue; } /* Clear the master setting if any */ if (masterable) { XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_MASTER, 0); } /* Clear the slaves setting if any */ XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_SLAVES, 0); printf("\n"); /* Pick the first available/capable display device as master */ if (pick_server && masterable) { /* Just pick the first enabled display */ unsigned int master = (1<<31); while (master && !(master & masterable)) { master >>= 1; } if (master) { mask &= ~master; /* Make sure we're not using the House Sync signal. */ XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK, framelock, // target_id 0, // display_mask NV_CTRL_USE_HOUSE_SYNC, NV_CTRL_USE_HOUSE_SYNC_FALSE); /* Set the master */ XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_MASTER, master); printf(" - Set Server Display : 0x%08x\n", master); pick_server = 0; server_set = 1; } } /* Set rest of enabled display devices as clients (slaves) */ if (mask) { XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_SLAVES, mask); printf(" - Set Client Display(s) : 0x%08x\n", mask); } /* Enable frame lock */ XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_SYNC, NV_CTRL_FRAMELOCK_SYNC_ENABLE); XFlush(dpy); printf(" - Frame Lock Sync Enabled.\n"); /* If we just enabled the server, also toggle the test signal * to guarentee accuracy of the universal frame count (as * returned by the glXQueryFrameCountNV() function in the * GLX_NV_swap_group extension). */ if (server_set) { XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_TEST_SIGNAL, NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE); XNVCTRLSetTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu, // target_id 0, // display_mask NV_CTRL_FRAMELOCK_TEST_SIGNAL, NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE); printf(" - Frame Lock Test Signal Toggled.\n"); server_set = 0; } } /* Done enabling GPUs */ XFree(data); } /* Done enabling framelocks */