proptest.c revision 08d7334d
108d7334dSsnj/*
208d7334dSsnj * Copyright © 2012 Intel Corporation
308d7334dSsnj *
408d7334dSsnj * Permission is hereby granted, free of charge, to any person obtaining a
508d7334dSsnj * copy of this software and associated documentation files (the "Software"),
608d7334dSsnj * to deal in the Software without restriction, including without limitation
708d7334dSsnj * the rights to use, copy, modify, merge, publish, distribute, sublicense,
808d7334dSsnj * and/or sell copies of the Software, and to permit persons to whom the
908d7334dSsnj * Software is furnished to do so, subject to the following conditions:
1008d7334dSsnj *
1108d7334dSsnj * The above copyright notice and this permission notice (including the next
1208d7334dSsnj * paragraph) shall be included in all copies or substantial portions of the
1308d7334dSsnj * Software.
1408d7334dSsnj *
1508d7334dSsnj * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1608d7334dSsnj * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1708d7334dSsnj * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1808d7334dSsnj * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1908d7334dSsnj * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2008d7334dSsnj * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2108d7334dSsnj * IN THE SOFTWARE.
2208d7334dSsnj *
2308d7334dSsnj * Authors:
2408d7334dSsnj *    Paulo Zanoni <paulo.r.zanoni@intel.com>
2508d7334dSsnj *
2608d7334dSsnj */
2708d7334dSsnj
2808d7334dSsnj#include <assert.h>
2908d7334dSsnj#include <errno.h>
3008d7334dSsnj#include <inttypes.h>
3108d7334dSsnj#include <stdlib.h>
3208d7334dSsnj#include <stdio.h>
3308d7334dSsnj#include <string.h>
3408d7334dSsnj
3508d7334dSsnj#include "xf86drm.h"
3608d7334dSsnj#include "xf86drmMode.h"
3708d7334dSsnj
3808d7334dSsnj#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
3908d7334dSsnjstatic inline int64_t U642I64(uint64_t val)
4008d7334dSsnj{
4108d7334dSsnj	return (int64_t)*((int64_t *)&val);
4208d7334dSsnj}
4308d7334dSsnj
4408d7334dSsnjint fd;
4508d7334dSsnjdrmModeResPtr res = NULL;
4608d7334dSsnj
4708d7334dSsnjconst char *connector_type_str(uint32_t type)
4808d7334dSsnj{
4908d7334dSsnj	switch (type) {
5008d7334dSsnj	case DRM_MODE_CONNECTOR_Unknown:
5108d7334dSsnj		return "Unknown";
5208d7334dSsnj	case DRM_MODE_CONNECTOR_VGA:
5308d7334dSsnj		return "VGA";
5408d7334dSsnj	case DRM_MODE_CONNECTOR_DVII:
5508d7334dSsnj		return "DVI-I";
5608d7334dSsnj	case DRM_MODE_CONNECTOR_DVID:
5708d7334dSsnj		return "DVI-D";
5808d7334dSsnj	case DRM_MODE_CONNECTOR_DVIA:
5908d7334dSsnj		return "DVI-A";
6008d7334dSsnj	case DRM_MODE_CONNECTOR_Composite:
6108d7334dSsnj		return "Composite";
6208d7334dSsnj	case DRM_MODE_CONNECTOR_SVIDEO:
6308d7334dSsnj		return "SVIDEO";
6408d7334dSsnj	case DRM_MODE_CONNECTOR_LVDS:
6508d7334dSsnj		return "LVDS";
6608d7334dSsnj	case DRM_MODE_CONNECTOR_Component:
6708d7334dSsnj		return "Component";
6808d7334dSsnj	case DRM_MODE_CONNECTOR_9PinDIN:
6908d7334dSsnj		return "9PinDin";
7008d7334dSsnj	case DRM_MODE_CONNECTOR_DisplayPort:
7108d7334dSsnj		return "DisplayPort";
7208d7334dSsnj	case DRM_MODE_CONNECTOR_HDMIA:
7308d7334dSsnj		return "HDMI-A";
7408d7334dSsnj	case DRM_MODE_CONNECTOR_HDMIB:
7508d7334dSsnj		return "HDMI-B";
7608d7334dSsnj	case DRM_MODE_CONNECTOR_TV:
7708d7334dSsnj		return "TV";
7808d7334dSsnj	case DRM_MODE_CONNECTOR_eDP:
7908d7334dSsnj		return "eDP";
8008d7334dSsnj	default:
8108d7334dSsnj		return "Invalid";
8208d7334dSsnj	}
8308d7334dSsnj}
8408d7334dSsnj
8508d7334dSsnj/* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */
8608d7334dSsnjstatic void
8708d7334dSsnjdump_blob(uint32_t blob_id)
8808d7334dSsnj{
8908d7334dSsnj	uint32_t i;
9008d7334dSsnj	unsigned char *blob_data;
9108d7334dSsnj	drmModePropertyBlobPtr blob;
9208d7334dSsnj
9308d7334dSsnj	blob = drmModeGetPropertyBlob(fd, blob_id);
9408d7334dSsnj	if (!blob) {
9508d7334dSsnj		printf("\n");
9608d7334dSsnj		return;
9708d7334dSsnj	}
9808d7334dSsnj
9908d7334dSsnj	blob_data = blob->data;
10008d7334dSsnj
10108d7334dSsnj	for (i = 0; i < blob->length; i++) {
10208d7334dSsnj		if (i % 16 == 0)
10308d7334dSsnj			printf("\n\t\t\t");
10408d7334dSsnj		printf("%.2hhx", blob_data[i]);
10508d7334dSsnj	}
10608d7334dSsnj	printf("\n");
10708d7334dSsnj
10808d7334dSsnj	drmModeFreePropertyBlob(blob);
10908d7334dSsnj}
11008d7334dSsnj
11108d7334dSsnjstatic void
11208d7334dSsnjdump_prop(uint32_t prop_id, uint64_t value)
11308d7334dSsnj{
11408d7334dSsnj	int i;
11508d7334dSsnj	drmModePropertyPtr prop;
11608d7334dSsnj
11708d7334dSsnj	prop = drmModeGetProperty(fd, prop_id);
11808d7334dSsnj
11908d7334dSsnj	printf("\t%d", prop_id);
12008d7334dSsnj	if (!prop) {
12108d7334dSsnj		printf("\n");
12208d7334dSsnj		return;
12308d7334dSsnj	}
12408d7334dSsnj
12508d7334dSsnj	printf(" %s:\n", prop->name);
12608d7334dSsnj
12708d7334dSsnj	printf("\t\tflags:");
12808d7334dSsnj	if (prop->flags & DRM_MODE_PROP_PENDING)
12908d7334dSsnj		printf(" pending");
13008d7334dSsnj	if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
13108d7334dSsnj		printf(" immutable");
13208d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
13308d7334dSsnj		printf(" signed range");
13408d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
13508d7334dSsnj		printf(" range");
13608d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
13708d7334dSsnj		printf(" enum");
13808d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
13908d7334dSsnj		printf(" bitmask");
14008d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
14108d7334dSsnj		printf(" blob");
14208d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
14308d7334dSsnj		printf(" object");
14408d7334dSsnj	printf("\n");
14508d7334dSsnj
14608d7334dSsnj
14708d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
14808d7334dSsnj		printf("\t\tvalues:");
14908d7334dSsnj		for (i = 0; i < prop->count_values; i++)
15008d7334dSsnj			printf(" %"PRId64, U642I64(prop->values[i]));
15108d7334dSsnj		printf("\n");
15208d7334dSsnj	}
15308d7334dSsnj
15408d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
15508d7334dSsnj		printf("\t\tvalues:");
15608d7334dSsnj		for (i = 0; i < prop->count_values; i++)
15708d7334dSsnj			printf(" %"PRIu64, prop->values[i]);
15808d7334dSsnj		printf("\n");
15908d7334dSsnj	}
16008d7334dSsnj
16108d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
16208d7334dSsnj		printf("\t\tenums:");
16308d7334dSsnj		for (i = 0; i < prop->count_enums; i++)
16408d7334dSsnj			printf(" %s=%llu", prop->enums[i].name,
16508d7334dSsnj			       prop->enums[i].value);
16608d7334dSsnj		printf("\n");
16708d7334dSsnj	} else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
16808d7334dSsnj		printf("\t\tvalues:");
16908d7334dSsnj		for (i = 0; i < prop->count_enums; i++)
17008d7334dSsnj			printf(" %s=0x%llx", prop->enums[i].name,
17108d7334dSsnj			       (1LL << prop->enums[i].value));
17208d7334dSsnj		printf("\n");
17308d7334dSsnj	} else {
17408d7334dSsnj		assert(prop->count_enums == 0);
17508d7334dSsnj	}
17608d7334dSsnj
17708d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
17808d7334dSsnj		printf("\t\tblobs:\n");
17908d7334dSsnj		for (i = 0; i < prop->count_blobs; i++)
18008d7334dSsnj			dump_blob(prop->blob_ids[i]);
18108d7334dSsnj		printf("\n");
18208d7334dSsnj	} else {
18308d7334dSsnj		assert(prop->count_blobs == 0);
18408d7334dSsnj	}
18508d7334dSsnj
18608d7334dSsnj	printf("\t\tvalue:");
18708d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
18808d7334dSsnj		dump_blob(value);
18908d7334dSsnj	else
19008d7334dSsnj		printf(" %"PRIu64"\n", value);
19108d7334dSsnj
19208d7334dSsnj	drmModeFreeProperty(prop);
19308d7334dSsnj}
19408d7334dSsnj
19508d7334dSsnjstatic void listObjectProperties(uint32_t id, uint32_t type)
19608d7334dSsnj{
19708d7334dSsnj	unsigned int i;
19808d7334dSsnj	drmModeObjectPropertiesPtr props;
19908d7334dSsnj
20008d7334dSsnj	props = drmModeObjectGetProperties(fd, id, type);
20108d7334dSsnj
20208d7334dSsnj	if (!props) {
20308d7334dSsnj		printf("\tNo properties: %s.\n", strerror(errno));
20408d7334dSsnj		return;
20508d7334dSsnj	}
20608d7334dSsnj
20708d7334dSsnj	for (i = 0; i < props->count_props; i++)
20808d7334dSsnj		dump_prop(props->props[i], props->prop_values[i]);
20908d7334dSsnj
21008d7334dSsnj	drmModeFreeObjectProperties(props);
21108d7334dSsnj}
21208d7334dSsnj
21308d7334dSsnjstatic void listConnectorProperties(void)
21408d7334dSsnj{
21508d7334dSsnj	int i;
21608d7334dSsnj	drmModeConnectorPtr c;
21708d7334dSsnj
21808d7334dSsnj	for (i = 0; i < res->count_connectors; i++) {
21908d7334dSsnj		c = drmModeGetConnector(fd, res->connectors[i]);
22008d7334dSsnj
22108d7334dSsnj		if (!c) {
22208d7334dSsnj			fprintf(stderr, "Could not get connector %u: %s\n",
22308d7334dSsnj				res->connectors[i], strerror(errno));
22408d7334dSsnj			continue;
22508d7334dSsnj		}
22608d7334dSsnj
22708d7334dSsnj		printf("Connector %u (%s-%u)\n", c->connector_id,
22808d7334dSsnj		       connector_type_str(c->connector_type),
22908d7334dSsnj		       c->connector_type_id);
23008d7334dSsnj
23108d7334dSsnj		listObjectProperties(c->connector_id,
23208d7334dSsnj				     DRM_MODE_OBJECT_CONNECTOR);
23308d7334dSsnj
23408d7334dSsnj		drmModeFreeConnector(c);
23508d7334dSsnj	}
23608d7334dSsnj}
23708d7334dSsnj
23808d7334dSsnjstatic void listCrtcProperties(void)
23908d7334dSsnj{
24008d7334dSsnj	int i;
24108d7334dSsnj	drmModeCrtcPtr c;
24208d7334dSsnj
24308d7334dSsnj	for (i = 0; i < res->count_crtcs; i++) {
24408d7334dSsnj		c = drmModeGetCrtc(fd, res->crtcs[i]);
24508d7334dSsnj
24608d7334dSsnj		if (!c) {
24708d7334dSsnj			fprintf(stderr, "Could not get crtc %u: %s\n",
24808d7334dSsnj				res->crtcs[i], strerror(errno));
24908d7334dSsnj			continue;
25008d7334dSsnj		}
25108d7334dSsnj
25208d7334dSsnj		printf("CRTC %u\n", c->crtc_id);
25308d7334dSsnj
25408d7334dSsnj		listObjectProperties(c->crtc_id, DRM_MODE_OBJECT_CRTC);
25508d7334dSsnj
25608d7334dSsnj		drmModeFreeCrtc(c);
25708d7334dSsnj	}
25808d7334dSsnj}
25908d7334dSsnj
26008d7334dSsnjstatic void listAllProperties(void)
26108d7334dSsnj{
26208d7334dSsnj	listConnectorProperties();
26308d7334dSsnj	listCrtcProperties();
26408d7334dSsnj}
26508d7334dSsnj
26608d7334dSsnjstatic int setProperty(char *argv[])
26708d7334dSsnj{
26808d7334dSsnj	uint32_t obj_id, obj_type, prop_id;
26908d7334dSsnj	uint64_t value;
27008d7334dSsnj
27108d7334dSsnj	obj_id = atoi(argv[1]);
27208d7334dSsnj
27308d7334dSsnj	if (!strcmp(argv[2], "connector")) {
27408d7334dSsnj		obj_type = DRM_MODE_OBJECT_CONNECTOR;
27508d7334dSsnj	} else if (!strcmp(argv[2], "crtc")) {
27608d7334dSsnj		obj_type = DRM_MODE_OBJECT_CRTC;
27708d7334dSsnj	} else {
27808d7334dSsnj		fprintf(stderr, "Invalid object type.\n");
27908d7334dSsnj		return 1;
28008d7334dSsnj	}
28108d7334dSsnj
28208d7334dSsnj	prop_id = atoi(argv[3]);
28308d7334dSsnj	value = atoll(argv[4]);
28408d7334dSsnj
28508d7334dSsnj	return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value);
28608d7334dSsnj}
28708d7334dSsnj
28808d7334dSsnjstatic void printUsage(void)
28908d7334dSsnj{
29008d7334dSsnj	printf("Usage:\n"
29108d7334dSsnj"  proptest\n"
29208d7334dSsnj"  proptest [obj id] [obj type] [prop id] [value]\n"
29308d7334dSsnj"\n"
29408d7334dSsnj"The first form just prints all the existing properties. The second one is\n"
29508d7334dSsnj"used to set the value of a specified property. The object type can be one of\n"
29608d7334dSsnj"the following strings:\n"
29708d7334dSsnj"  connector crtc\n"
29808d7334dSsnj"\n"
29908d7334dSsnj"Example:\n"
30008d7334dSsnj"  proptest 7 connector 2 1\n"
30108d7334dSsnj"will set property 2 of connector 7 to 1\n");
30208d7334dSsnj}
30308d7334dSsnj
30408d7334dSsnjint main(int argc, char *argv[])
30508d7334dSsnj{
30608d7334dSsnj	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "msm" };
30708d7334dSsnj	unsigned int i, ret = 0;
30808d7334dSsnj
30908d7334dSsnj	for (i = 0; i < ARRAY_SIZE(modules); i++){
31008d7334dSsnj		fd = drmOpen(modules[i], NULL);
31108d7334dSsnj		if (fd >= 0) {
31208d7334dSsnj			printf("Module %s loaded.\n", modules[i]);
31308d7334dSsnj			break;
31408d7334dSsnj		}
31508d7334dSsnj	}
31608d7334dSsnj
31708d7334dSsnj	if (i == ARRAY_SIZE(modules)) {
31808d7334dSsnj		fprintf(stderr, "Failed to load drm modules.\n");
31908d7334dSsnj		return 1;
32008d7334dSsnj	}
32108d7334dSsnj
32208d7334dSsnj	res = drmModeGetResources(fd);
32308d7334dSsnj	if (!res) {
32408d7334dSsnj		fprintf(stderr, "Failed to get resources: %s\n",
32508d7334dSsnj			strerror(errno));
32608d7334dSsnj		ret = 1;
32708d7334dSsnj		goto done;
32808d7334dSsnj	}
32908d7334dSsnj
33008d7334dSsnj	if (argc < 2) {
33108d7334dSsnj		listAllProperties();
33208d7334dSsnj	} else if (argc == 5) {
33308d7334dSsnj		ret = setProperty(argv);
33408d7334dSsnj	} else {
33508d7334dSsnj		printUsage();
33608d7334dSsnj		ret = 1;
33708d7334dSsnj	}
33808d7334dSsnj
33908d7334dSsnj	drmModeFreeResources(res);
34008d7334dSsnjdone:
34108d7334dSsnj	drmClose(fd);
34208d7334dSsnj	return ret;
34308d7334dSsnj}
344