* nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
* and Linux systems.
*
* Copyright (C) 2004 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#include "NvCtrlAttributes.h"
#include "NvCtrlAttributesPrivate.h"
#include "NVCtrlLib.h"
#include "common-utils.h"
#include "msg.h"
#include <stdlib.h>
#include <string.h>
* NvCtrlInitNvControlAttributes() - check for the NV-CONTROL
* extension and make sure we have an adequate version. Returns a
* malloced and initialized NvCtrlNvControlAttributes structure if
* successful, or NULL otherwise.
*/
NvCtrlNvControlAttributes *
NvCtrlInitNvControlAttributes (NvCtrlAttributePrivateHandle *h)
{
NvCtrlNvControlAttributes *nv;
int ret, major, minor, event, error;
const CtrlTargetTypeInfo *targetTypeInfo;
if (!h->dpy) {
nv_warning_msg("NV-CONTROL Display not found.");
return NULL;
}
ret = XNVCTRLQueryExtension (h->dpy, &event, &error);
if (ret != True) {
nv_warning_msg("NV-CONTROL extension not found on this Display.");
return NULL;
}
ret = XNVCTRLQueryVersion (h->dpy, &major, &minor);
if (ret != True) {
nv_error_msg("Failed to query NV-CONTROL extension version.");
return NULL;
}
if (NV_VERSION2(major, minor) < NV_VERSION2(NV_MINMAJOR, NV_MINMINOR)) {
nv_error_msg("NV-CONTROL extension version %d.%d is too old; "
"the minimum required version is %d.%d.",
major, minor, NV_MINMAJOR, NV_MINMINOR);
return NULL;
}
if (h->target_type == X_SCREEN_TARGET) {
ret = XNVCTRLIsNvScreen (h->dpy, h->target_id);
if (ret != True) {
nv_warning_msg("NV-CONTROL extension not present on screen %d "
"of this Display.", h->target_id);
return NULL;
}
}
nv = nvalloc(sizeof(NvCtrlNvControlAttributes));
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
nv_error_msg("Invalid or unknown target type");
return NULL;
}
ret = XNVCtrlSelectTargetNotify(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
TARGET_ATTRIBUTE_CHANGED_EVENT,
True);
if (ret != True) {
nv_warning_msg("Unable to select attribute changed NV-CONTROL "
"events.");
}
* TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT was added in NV-CONTROL
* 1.15
*/
if (NV_VERSION2(major, minor) >= NV_VERSION2(1, 15)) {
ret = XNVCtrlSelectTargetNotify(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT,
True);
if (ret != True) {
nv_warning_msg("Unable to select attribute changed NV-CONTROL "
"events.");
}
}
* TARGET_STRING_ATTRIBUTE_CHANGED_EVENT was added in NV-CONTROL
* 1.16
*/
if (NV_VERSION2(major, minor) >= NV_VERSION2(1, 16)) {
ret = XNVCtrlSelectTargetNotify(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
TARGET_STRING_ATTRIBUTE_CHANGED_EVENT,
True);
if (ret != True) {
nv_warning_msg("Unable to select attribute changed NV-CONTROL string"
"events.");
}
}
* TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT was added in NV-CONTROL
* 1.17
*/
if (NV_VERSION2(major, minor) >= NV_VERSION2(1, 17)) {
ret = XNVCtrlSelectTargetNotify(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT,
True);
if (ret != True) {
nv_warning_msg("Unable to select attribute changed NV-CONTROL binary"
"events.");
}
}
nv->event_base = event;
nv->error_base = error;
nv->major_version = major;
nv->minor_version = minor;
return (nv);
}
ReturnStatus
NvCtrlNvControlQueryTargetCount(const NvCtrlAttributePrivateHandle *h,
CtrlTargetType target_type, int *val)
{
int ret;
const CtrlTargetTypeInfo *targetTypeInfo;
targetTypeInfo = NvCtrlGetTargetTypeInfo(target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadArgument;
}
if (!h->dpy) {
nv_warning_msg("NV-CONTROL Display not found.");
return NvCtrlError;
}
ret = XNVCTRLQueryTargetCount(h->dpy, targetTypeInfo->nvctrl, val);
return (ret) ? NvCtrlSuccess : NvCtrlError;
}
ReturnStatus NvCtrlNvControlGetAttribute(const NvCtrlAttributePrivateHandle *h,
unsigned int display_mask,
int attr, int64_t *val)
{
ReturnStatus status;
int value_32;
int major, minor;
if (!h->nv) {
return NvCtrlMissingExtension;
}
major = h->nv->major_version;
minor = h->nv->minor_version;
if (attr <= NV_CTRL_LAST_ATTRIBUTE) {
const CtrlTargetTypeInfo *targetTypeInfo;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
if (NV_VERSION2(major, minor) > NV_VERSION2(1, 20)) {
status = XNVCTRLQueryTargetAttribute64(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
display_mask, attr,
val);
} else {
status = XNVCTRLQueryTargetAttribute(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
display_mask, attr,
&value_32);
*val = value_32;
}
if (status) {
return NvCtrlSuccess;
} else {
return NvCtrlAttributeNotAvailable;
}
}
if ((attr >= NV_CTRL_ATTR_NV_BASE) &&
(attr <= NV_CTRL_ATTR_NV_LAST_ATTRIBUTE)) {
if (!h->nv) return NvCtrlMissingExtension;
switch (attr) {
case NV_CTRL_ATTR_NV_MAJOR_VERSION:
*val = major;
return NvCtrlSuccess;
case NV_CTRL_ATTR_NV_MINOR_VERSION:
*val = minor;
return NvCtrlSuccess;
}
}
return NvCtrlNoAttribute;
}
ReturnStatus NvCtrlNvControlSetAttribute (NvCtrlAttributePrivateHandle *h,
unsigned int display_mask,
int attr, int val)
{
if (attr <= NV_CTRL_LAST_ATTRIBUTE) {
Bool bRet;
const CtrlTargetTypeInfo *targetTypeInfo;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
bRet = XNVCTRLSetTargetAttributeAndGetStatus(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
display_mask, attr, val);
if (!bRet) {
return NvCtrlError;
}
return NvCtrlSuccess;
}
return NvCtrlNoAttribute;
}
* Helper function for converting NV-CONTROL specific permission data into
* CtrlAttributePerms (API agnostic) permission data that the front-end can use.
*/
static void convertFromNvCtrlPermissions(CtrlAttributePerms *dst,
unsigned int permissions)
{
memset(dst, 0, sizeof(*dst));
dst->read = (permissions & ATTRIBUTE_TYPE_READ) ? NV_TRUE : NV_FALSE;
dst->write = (permissions & ATTRIBUTE_TYPE_WRITE) ? NV_TRUE : NV_FALSE;
if (permissions & ATTRIBUTE_TYPE_X_SCREEN) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(X_SCREEN_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_DISPLAY) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(DISPLAY_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_GPU) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(GPU_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_FRAMELOCK) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(FRAMELOCK_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_COOLER) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(COOLER_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_THERMAL_SENSOR) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(THERMAL_SENSOR_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER) {
dst->valid_targets |=
CTRL_TARGET_PERM_BIT(NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET);
}
if (permissions & ATTRIBUTE_TYPE_MUX) {
dst->valid_targets |= CTRL_TARGET_PERM_BIT(MUX_TARGET);
}
}
ReturnStatus
NvCtrlNvControlGetAttributePerms(const NvCtrlAttributePrivateHandle *h,
CtrlAttributeType attr_type, int attr,
CtrlAttributePerms *perms)
{
NVCTRLAttributePermissionsRec nvctrlPerms;
switch (attr_type) {
case CTRL_ATTRIBUTE_TYPE_INTEGER:
XNVCTRLQueryAttributePermissions(h->dpy, attr, &nvctrlPerms);
convertFromNvCtrlPermissions(perms, nvctrlPerms.permissions);
break;
case CTRL_ATTRIBUTE_TYPE_STRING:
XNVCTRLQueryStringAttributePermissions(h->dpy, attr, &nvctrlPerms);
convertFromNvCtrlPermissions(perms, nvctrlPerms.permissions);
break;
case CTRL_ATTRIBUTE_TYPE_BINARY_DATA:
XNVCTRLQueryBinaryDataAttributePermissions(h->dpy, attr, &nvctrlPerms);
convertFromNvCtrlPermissions(perms, nvctrlPerms.permissions);
break;
case CTRL_ATTRIBUTE_TYPE_STRING_OPERATION:
XNVCTRLQueryStringOperationAttributePermissions(h->dpy, attr,
&nvctrlPerms);
convertFromNvCtrlPermissions(perms, nvctrlPerms.permissions);
break;
default:
return NvCtrlBadArgument;
}
return NvCtrlSuccess;
}
* Helper function for converting NV-CONTROL specific valid values data into
* CtrlAttributeValidValues (API agnostic) data that the front-end can use.
*/
static void
convertFromNvCtrlValidValues(CtrlAttributeValidValues *dst,
const NVCTRLAttributeValidValuesRec *src)
{
memset(dst, 0, sizeof(*dst));
switch (src->type) {
case ATTRIBUTE_TYPE_INTEGER:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_INTEGER;
break;
case ATTRIBUTE_TYPE_BITMASK:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BITMASK;
break;
case ATTRIBUTE_TYPE_BOOL:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BOOL;
break;
case ATTRIBUTE_TYPE_RANGE:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_RANGE;
break;
case ATTRIBUTE_TYPE_INT_BITS:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_INT_BITS;
break;
case ATTRIBUTE_TYPE_64BIT_INTEGER:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER;
break;
case ATTRIBUTE_TYPE_STRING:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING;
break;
case ATTRIBUTE_TYPE_BINARY_DATA:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BINARY_DATA;
break;
case ATTRIBUTE_TYPE_STRING_OPERATION:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING_OPERATION;
break;
default:
dst->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_UNKNOWN;
}
if (src->type == ATTRIBUTE_TYPE_RANGE) {
dst->range.min = src->u.range.min;
dst->range.max = src->u.range.max;
}
else if (src->type == ATTRIBUTE_TYPE_INT_BITS) {
dst->allowed_ints = src->u.bits.ints;
}
convertFromNvCtrlPermissions(&(dst->permissions), src->permissions);
}
ReturnStatus
NvCtrlNvControlGetValidAttributeValues(const NvCtrlAttributePrivateHandle *h,
unsigned int display_mask,
int attr,
CtrlAttributeValidValues *val)
{
if (attr <= NV_CTRL_LAST_ATTRIBUTE) {
const CtrlTargetTypeInfo *targetTypeInfo;
NVCTRLAttributeValidValuesRec valid;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
if (XNVCTRLQueryValidTargetAttributeValues(h->dpy,
targetTypeInfo->nvctrl,
h->target_id, display_mask,
attr, &valid)) {
if (val != NULL) {
convertFromNvCtrlValidValues(val, &valid);
}
return NvCtrlSuccess;
} else {
return NvCtrlAttributeNotAvailable;
}
}
return NvCtrlNoAttribute;
}
ReturnStatus
NvCtrlNvControlGetValidStringDisplayAttributeValues
(const NvCtrlAttributePrivateHandle *h,
unsigned int display_mask,
int attr,
CtrlAttributeValidValues *val)
{
if (attr <= NV_CTRL_STRING_LAST_ATTRIBUTE) {
if (NV_VERSION2(h->nv->major_version, h->nv->minor_version)
>= NV_VERSION2(1, 22)) {
const CtrlTargetTypeInfo *targetTypeInfo;
NVCTRLAttributeValidValuesRec valid;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
if (XNVCTRLQueryValidTargetStringAttributeValues(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
display_mask,
attr, &valid)) {
if (val != NULL) {
convertFromNvCtrlValidValues(val, &valid);
}
return NvCtrlSuccess;
} else {
return NvCtrlAttributeNotAvailable;
}
} else {
if (val) {
memset(val, 0, sizeof(*val));
val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING;
val->permissions.read = NV_TRUE;
val->permissions.valid_targets = CTRL_TARGET_PERM_BIT(X_SCREEN_TARGET);
return NvCtrlSuccess;
} else {
return NvCtrlBadArgument;
}
}
}
return NvCtrlNoAttribute;
}
ReturnStatus
NvCtrlNvControlGetStringAttribute(const NvCtrlAttributePrivateHandle *h,
unsigned int display_mask,
int attr, char **ptr)
{
if (!h || !h->dpy) {
return NvCtrlBadHandle;
}
if (attr == NV_CTRL_STRING_NV_CONTROL_VERSION) {
char str[24];
if (h->target_type != X_SCREEN_TARGET) {
return NvCtrlBadHandle;
}
sprintf(str, "%d.%d", h->nv->major_version, h->nv->minor_version);
*ptr = strdup(str);
return NvCtrlSuccess;
}
if (attr <= NV_CTRL_STRING_LAST_ATTRIBUTE) {
char *tmp;
const CtrlTargetTypeInfo *targetTypeInfo;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
if (XNVCTRLQueryTargetStringAttribute(h->dpy,
targetTypeInfo->nvctrl,
h->target_id, display_mask,
attr, &tmp)) {
if (tmp) {
*ptr = strdup(tmp);
XFree(tmp);
} else {
*ptr = NULL;
}
return NvCtrlSuccess;
} else {
return NvCtrlAttributeNotAvailable;
}
}
return NvCtrlNoAttribute;
}
ReturnStatus
NvCtrlNvControlSetStringAttribute (NvCtrlAttributePrivateHandle *h,
unsigned int display_mask,
int attr, const char *ptr)
{
if (attr <= NV_CTRL_LAST_ATTRIBUTE) {
Bool ret;
* on targets other than X screens.
*/
if (NV_VERSION2(h->nv->major_version, h->nv->minor_version) >=
NV_VERSION2(1, 19)) {
const CtrlTargetTypeInfo *targetTypeInfo;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
ret = XNVCTRLSetTargetStringAttribute(h->dpy,
targetTypeInfo->nvctrl,
h->target_id, display_mask,
attr, ptr);
} else {
if (h->target_type != X_SCREEN_TARGET) {
return NvCtrlBadHandle;
}
ret =
XNVCTRLSetStringAttribute(h->dpy, h->target_id, display_mask,
attr, ptr);
}
if ( ret ) {
return NvCtrlSuccess;
} else {
return NvCtrlAttributeNotAvailable;
}
}
return NvCtrlNoAttribute;
}
ReturnStatus
NvCtrlNvControlGetBinaryAttribute(const NvCtrlAttributePrivateHandle *h,
unsigned int display_mask, int attr,
unsigned char **data, int *len)
{
unsigned char *tmp;
Bool ret;
int localLen;
const CtrlTargetTypeInfo *targetTypeInfo;
if (!h->nv) return NvCtrlMissingExtension;
if (NV_VERSION2(h->nv->major_version, h->nv->minor_version) <
NV_VERSION2(1, 7)) {
return NvCtrlNoAttribute;
}
if (len == NULL) {
len = &localLen;
}
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
ret = XNVCTRLQueryTargetBinaryData(h->dpy,
targetTypeInfo->nvctrl,
h->target_id,
display_mask, attr, &tmp, len);
if (!ret) {
return NvCtrlError;
}
if (tmp == NULL) {
*data = NULL;
return NvCtrlSuccess;
}
*data = malloc(*len);
if (*data == NULL) {
*len = 0;
XFree(tmp);
return NvCtrlError;
}
memcpy(*data, tmp, *len);
XFree(tmp);
return NvCtrlSuccess;
}
ReturnStatus
NvCtrlNvControlStringOperation(NvCtrlAttributePrivateHandle *h,
unsigned int display_mask, int attr,
const char *ptrIn, char **ptrOut)
{
char *tmp;
if (attr <= NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE) {
const CtrlTargetTypeInfo *targetTypeInfo;
targetTypeInfo = NvCtrlGetTargetTypeInfo(h->target_type);
if (targetTypeInfo == NULL) {
return NvCtrlBadHandle;
}
if (XNVCTRLStringOperation(h->dpy, targetTypeInfo->nvctrl,
h->target_id, display_mask,
attr, ptrIn, &tmp)) {
if (tmp) {
*ptrOut = strdup(tmp);
XFree(tmp);
} else {
*ptrOut = NULL;
}
return NvCtrlSuccess;
} else {
return NvCtrlAttributeNotAvailable;
}
}
return NvCtrlNoAttribute;
}