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>
303f012e29Smrg#include <getopt.h>
3108d7334dSsnj#include <inttypes.h>
3208d7334dSsnj#include <stdlib.h>
3308d7334dSsnj#include <stdio.h>
3408d7334dSsnj#include <string.h>
3508d7334dSsnj
3608d7334dSsnj#include "xf86drm.h"
3708d7334dSsnj#include "xf86drmMode.h"
3808d7334dSsnj
393f012e29Smrg#include "util/common.h"
403f012e29Smrg#include "util/kms.h"
413f012e29Smrg
4208d7334dSsnjstatic inline int64_t U642I64(uint64_t val)
4308d7334dSsnj{
4408d7334dSsnj	return (int64_t)*((int64_t *)&val);
4508d7334dSsnj}
4608d7334dSsnj
4708d7334dSsnjint fd;
4808d7334dSsnjdrmModeResPtr res = NULL;
4908d7334dSsnj
5008d7334dSsnj/* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */
5108d7334dSsnjstatic void
5208d7334dSsnjdump_blob(uint32_t blob_id)
5308d7334dSsnj{
5408d7334dSsnj	uint32_t i;
5508d7334dSsnj	unsigned char *blob_data;
5608d7334dSsnj	drmModePropertyBlobPtr blob;
5708d7334dSsnj
5808d7334dSsnj	blob = drmModeGetPropertyBlob(fd, blob_id);
5908d7334dSsnj	if (!blob) {
6008d7334dSsnj		printf("\n");
6108d7334dSsnj		return;
6208d7334dSsnj	}
6308d7334dSsnj
6408d7334dSsnj	blob_data = blob->data;
6508d7334dSsnj
6608d7334dSsnj	for (i = 0; i < blob->length; i++) {
6708d7334dSsnj		if (i % 16 == 0)
6808d7334dSsnj			printf("\n\t\t\t");
6908d7334dSsnj		printf("%.2hhx", blob_data[i]);
7008d7334dSsnj	}
7108d7334dSsnj	printf("\n");
7208d7334dSsnj
7308d7334dSsnj	drmModeFreePropertyBlob(blob);
7408d7334dSsnj}
7508d7334dSsnj
7608d7334dSsnjstatic void
7708d7334dSsnjdump_prop(uint32_t prop_id, uint64_t value)
7808d7334dSsnj{
7908d7334dSsnj	int i;
8008d7334dSsnj	drmModePropertyPtr prop;
8108d7334dSsnj
8208d7334dSsnj	prop = drmModeGetProperty(fd, prop_id);
8308d7334dSsnj
8408d7334dSsnj	printf("\t%d", prop_id);
8508d7334dSsnj	if (!prop) {
8608d7334dSsnj		printf("\n");
8708d7334dSsnj		return;
8808d7334dSsnj	}
8908d7334dSsnj
9008d7334dSsnj	printf(" %s:\n", prop->name);
9108d7334dSsnj
9208d7334dSsnj	printf("\t\tflags:");
9308d7334dSsnj	if (prop->flags & DRM_MODE_PROP_PENDING)
9408d7334dSsnj		printf(" pending");
9508d7334dSsnj	if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
9608d7334dSsnj		printf(" immutable");
9708d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
9808d7334dSsnj		printf(" signed range");
9908d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
10008d7334dSsnj		printf(" range");
10108d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
10208d7334dSsnj		printf(" enum");
10308d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
10408d7334dSsnj		printf(" bitmask");
10508d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
10608d7334dSsnj		printf(" blob");
10708d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
10808d7334dSsnj		printf(" object");
10908d7334dSsnj	printf("\n");
11008d7334dSsnj
11108d7334dSsnj
11208d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
11308d7334dSsnj		printf("\t\tvalues:");
11408d7334dSsnj		for (i = 0; i < prop->count_values; i++)
11508d7334dSsnj			printf(" %"PRId64, U642I64(prop->values[i]));
11608d7334dSsnj		printf("\n");
11708d7334dSsnj	}
11808d7334dSsnj
11908d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
12008d7334dSsnj		printf("\t\tvalues:");
12108d7334dSsnj		for (i = 0; i < prop->count_values; i++)
12208d7334dSsnj			printf(" %"PRIu64, prop->values[i]);
12308d7334dSsnj		printf("\n");
12408d7334dSsnj	}
12508d7334dSsnj
12608d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
12708d7334dSsnj		printf("\t\tenums:");
12808d7334dSsnj		for (i = 0; i < prop->count_enums; i++)
12949ef06a4Smrg			printf(" %s=%"PRIu64, prop->enums[i].name,
1300ed5401bSmrg			       (uint64_t)prop->enums[i].value);
13108d7334dSsnj		printf("\n");
13208d7334dSsnj	} else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
13308d7334dSsnj		printf("\t\tvalues:");
13408d7334dSsnj		for (i = 0; i < prop->count_enums; i++)
13508d7334dSsnj			printf(" %s=0x%llx", prop->enums[i].name,
13608d7334dSsnj			       (1LL << prop->enums[i].value));
13708d7334dSsnj		printf("\n");
13808d7334dSsnj	} else {
13908d7334dSsnj		assert(prop->count_enums == 0);
14008d7334dSsnj	}
14108d7334dSsnj
14208d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
14308d7334dSsnj		printf("\t\tblobs:\n");
14408d7334dSsnj		for (i = 0; i < prop->count_blobs; i++)
14508d7334dSsnj			dump_blob(prop->blob_ids[i]);
14608d7334dSsnj		printf("\n");
14708d7334dSsnj	} else {
14808d7334dSsnj		assert(prop->count_blobs == 0);
14908d7334dSsnj	}
15008d7334dSsnj
15108d7334dSsnj	printf("\t\tvalue:");
15208d7334dSsnj	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
15308d7334dSsnj		dump_blob(value);
1543f012e29Smrg	else if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
1553f012e29Smrg		printf(" %"PRId64"\n", value);
15608d7334dSsnj	else
15708d7334dSsnj		printf(" %"PRIu64"\n", value);
15808d7334dSsnj
15908d7334dSsnj	drmModeFreeProperty(prop);
16008d7334dSsnj}
16108d7334dSsnj
16208d7334dSsnjstatic void listObjectProperties(uint32_t id, uint32_t type)
16308d7334dSsnj{
16408d7334dSsnj	unsigned int i;
16508d7334dSsnj	drmModeObjectPropertiesPtr props;
16608d7334dSsnj
16708d7334dSsnj	props = drmModeObjectGetProperties(fd, id, type);
16808d7334dSsnj
16908d7334dSsnj	if (!props) {
17008d7334dSsnj		printf("\tNo properties: %s.\n", strerror(errno));
17108d7334dSsnj		return;
17208d7334dSsnj	}
17308d7334dSsnj
17408d7334dSsnj	for (i = 0; i < props->count_props; i++)
17508d7334dSsnj		dump_prop(props->props[i], props->prop_values[i]);
17608d7334dSsnj
17708d7334dSsnj	drmModeFreeObjectProperties(props);
17808d7334dSsnj}
17908d7334dSsnj
18008d7334dSsnjstatic void listConnectorProperties(void)
18108d7334dSsnj{
18208d7334dSsnj	int i;
18308d7334dSsnj	drmModeConnectorPtr c;
18408d7334dSsnj
18508d7334dSsnj	for (i = 0; i < res->count_connectors; i++) {
18608d7334dSsnj		c = drmModeGetConnector(fd, res->connectors[i]);
18708d7334dSsnj
18808d7334dSsnj		if (!c) {
18908d7334dSsnj			fprintf(stderr, "Could not get connector %u: %s\n",
19008d7334dSsnj				res->connectors[i], strerror(errno));
19108d7334dSsnj			continue;
19208d7334dSsnj		}
19308d7334dSsnj
19408d7334dSsnj		printf("Connector %u (%s-%u)\n", c->connector_id,
1950ed5401bSmrg		       drmModeGetConnectorTypeName(c->connector_type),
19608d7334dSsnj		       c->connector_type_id);
19708d7334dSsnj
19808d7334dSsnj		listObjectProperties(c->connector_id,
19908d7334dSsnj				     DRM_MODE_OBJECT_CONNECTOR);
20008d7334dSsnj
20108d7334dSsnj		drmModeFreeConnector(c);
20208d7334dSsnj	}
20308d7334dSsnj}
20408d7334dSsnj
20508d7334dSsnjstatic void listCrtcProperties(void)
20608d7334dSsnj{
20708d7334dSsnj	int i;
20808d7334dSsnj	drmModeCrtcPtr c;
20908d7334dSsnj
21008d7334dSsnj	for (i = 0; i < res->count_crtcs; i++) {
21108d7334dSsnj		c = drmModeGetCrtc(fd, res->crtcs[i]);
21208d7334dSsnj
21308d7334dSsnj		if (!c) {
21408d7334dSsnj			fprintf(stderr, "Could not get crtc %u: %s\n",
21508d7334dSsnj				res->crtcs[i], strerror(errno));
21608d7334dSsnj			continue;
21708d7334dSsnj		}
21808d7334dSsnj
21908d7334dSsnj		printf("CRTC %u\n", c->crtc_id);
22008d7334dSsnj
22108d7334dSsnj		listObjectProperties(c->crtc_id, DRM_MODE_OBJECT_CRTC);
22208d7334dSsnj
22308d7334dSsnj		drmModeFreeCrtc(c);
22408d7334dSsnj	}
22508d7334dSsnj}
22608d7334dSsnj
22708d7334dSsnjstatic void listAllProperties(void)
22808d7334dSsnj{
22908d7334dSsnj	listConnectorProperties();
23008d7334dSsnj	listCrtcProperties();
23108d7334dSsnj}
23208d7334dSsnj
23308d7334dSsnjstatic int setProperty(char *argv[])
23408d7334dSsnj{
23508d7334dSsnj	uint32_t obj_id, obj_type, prop_id;
23608d7334dSsnj	uint64_t value;
23708d7334dSsnj
2383f012e29Smrg	obj_id = atoi(argv[0]);
23908d7334dSsnj
2403f012e29Smrg	if (!strcmp(argv[1], "connector")) {
24108d7334dSsnj		obj_type = DRM_MODE_OBJECT_CONNECTOR;
2423f012e29Smrg	} else if (!strcmp(argv[1], "crtc")) {
24308d7334dSsnj		obj_type = DRM_MODE_OBJECT_CRTC;
24408d7334dSsnj	} else {
24508d7334dSsnj		fprintf(stderr, "Invalid object type.\n");
24608d7334dSsnj		return 1;
24708d7334dSsnj	}
24808d7334dSsnj
2493f012e29Smrg	prop_id = atoi(argv[2]);
2503f012e29Smrg	value = atoll(argv[3]);
25108d7334dSsnj
25208d7334dSsnj	return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value);
25308d7334dSsnj}
25408d7334dSsnj
2553f012e29Smrgstatic void usage(const char *program)
25608d7334dSsnj{
25708d7334dSsnj	printf("Usage:\n"
2583f012e29Smrg"  %s [options]\n"
2593f012e29Smrg"  %s [options] [obj id] [obj type] [prop id] [value]\n"
2603f012e29Smrg"\n"
2613f012e29Smrg"options:\n"
2623f012e29Smrg"  -D DEVICE  use the given device\n"
2633f012e29Smrg"  -M MODULE  use the given driver\n"
26408d7334dSsnj"\n"
26508d7334dSsnj"The first form just prints all the existing properties. The second one is\n"
26608d7334dSsnj"used to set the value of a specified property. The object type can be one of\n"
26708d7334dSsnj"the following strings:\n"
26808d7334dSsnj"  connector crtc\n"
26908d7334dSsnj"\n"
27008d7334dSsnj"Example:\n"
27108d7334dSsnj"  proptest 7 connector 2 1\n"
2723f012e29Smrg"will set property 2 of connector 7 to 1\n", program, program);
27308d7334dSsnj}
27408d7334dSsnj
27508d7334dSsnjint main(int argc, char *argv[])
27608d7334dSsnj{
2773f012e29Smrg	static const char optstr[] = "D:M:";
2783f012e29Smrg	int c, args, ret = 0;
2793f012e29Smrg	char *device = NULL;
2803f012e29Smrg	char *module = NULL;
2813f012e29Smrg
2823f012e29Smrg	while ((c = getopt(argc, argv, optstr)) != -1) {
2833f012e29Smrg		switch (c) {
2843f012e29Smrg		case 'D':
2853f012e29Smrg			device = optarg;
2863f012e29Smrg			break;
2873f012e29Smrg
2883f012e29Smrg		case 'M':
2893f012e29Smrg			module = optarg;
2903f012e29Smrg			break;
29108d7334dSsnj
2923f012e29Smrg		default:
2933f012e29Smrg			usage(argv[0]);
29408d7334dSsnj			break;
29508d7334dSsnj		}
29608d7334dSsnj	}
29708d7334dSsnj
2983f012e29Smrg	args = argc - optind;
2993f012e29Smrg
3003f012e29Smrg	fd = util_open(device, module);
3013f012e29Smrg	if (fd < 0)
30208d7334dSsnj		return 1;
30308d7334dSsnj
30408d7334dSsnj	res = drmModeGetResources(fd);
30508d7334dSsnj	if (!res) {
30608d7334dSsnj		fprintf(stderr, "Failed to get resources: %s\n",
30708d7334dSsnj			strerror(errno));
30808d7334dSsnj		ret = 1;
30908d7334dSsnj		goto done;
31008d7334dSsnj	}
31108d7334dSsnj
3123f012e29Smrg	if (args < 1) {
31308d7334dSsnj		listAllProperties();
3143f012e29Smrg	} else if (args == 4) {
3153f012e29Smrg		ret = setProperty(&argv[optind]);
31608d7334dSsnj	} else {
3173f012e29Smrg		usage(argv[0]);
31808d7334dSsnj		ret = 1;
31908d7334dSsnj	}
32008d7334dSsnj
32108d7334dSsnj	drmModeFreeResources(res);
32208d7334dSsnjdone:
32308d7334dSsnj	drmClose(fd);
32408d7334dSsnj	return ret;
32508d7334dSsnj}
326