1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright © 2012 Intel Corporation
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next
12d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13d722e3fbSopenharmony_ci * Software.
14d722e3fbSopenharmony_ci *
15d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18d722e3fbSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19d722e3fbSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20d722e3fbSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21d722e3fbSopenharmony_ci * IN THE SOFTWARE.
22d722e3fbSopenharmony_ci *
23d722e3fbSopenharmony_ci * Authors:
24d722e3fbSopenharmony_ci *    Paulo Zanoni <paulo.r.zanoni@intel.com>
25d722e3fbSopenharmony_ci *
26d722e3fbSopenharmony_ci */
27d722e3fbSopenharmony_ci
28d722e3fbSopenharmony_ci#include <assert.h>
29d722e3fbSopenharmony_ci#include <errno.h>
30d722e3fbSopenharmony_ci#include <getopt.h>
31d722e3fbSopenharmony_ci#include <inttypes.h>
32d722e3fbSopenharmony_ci#include <stdlib.h>
33d722e3fbSopenharmony_ci#include <stdio.h>
34d722e3fbSopenharmony_ci#include <string.h>
35d722e3fbSopenharmony_ci
36d722e3fbSopenharmony_ci#include "xf86drm.h"
37d722e3fbSopenharmony_ci#include "xf86drmMode.h"
38d722e3fbSopenharmony_ci
39d722e3fbSopenharmony_ci#include "util/common.h"
40d722e3fbSopenharmony_ci#include "util/kms.h"
41d722e3fbSopenharmony_ci
42d722e3fbSopenharmony_cistatic inline int64_t U642I64(uint64_t val)
43d722e3fbSopenharmony_ci{
44d722e3fbSopenharmony_ci	return (int64_t)*((int64_t *)&val);
45d722e3fbSopenharmony_ci}
46d722e3fbSopenharmony_ci
47d722e3fbSopenharmony_ciint fd;
48d722e3fbSopenharmony_cidrmModeResPtr res = NULL;
49d722e3fbSopenharmony_ci
50d722e3fbSopenharmony_ci/* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */
51d722e3fbSopenharmony_cistatic void
52d722e3fbSopenharmony_cidump_blob(uint32_t blob_id)
53d722e3fbSopenharmony_ci{
54d722e3fbSopenharmony_ci	uint32_t i;
55d722e3fbSopenharmony_ci	unsigned char *blob_data;
56d722e3fbSopenharmony_ci	drmModePropertyBlobPtr blob;
57d722e3fbSopenharmony_ci
58d722e3fbSopenharmony_ci	blob = drmModeGetPropertyBlob(fd, blob_id);
59d722e3fbSopenharmony_ci	if (!blob) {
60d722e3fbSopenharmony_ci		printf("\n");
61d722e3fbSopenharmony_ci		return;
62d722e3fbSopenharmony_ci	}
63d722e3fbSopenharmony_ci
64d722e3fbSopenharmony_ci	blob_data = blob->data;
65d722e3fbSopenharmony_ci
66d722e3fbSopenharmony_ci	for (i = 0; i < blob->length; i++) {
67d722e3fbSopenharmony_ci		if (i % 16 == 0)
68d722e3fbSopenharmony_ci			printf("\n\t\t\t");
69d722e3fbSopenharmony_ci		printf("%.2hhx", blob_data[i]);
70d722e3fbSopenharmony_ci	}
71d722e3fbSopenharmony_ci	printf("\n");
72d722e3fbSopenharmony_ci
73d722e3fbSopenharmony_ci	drmModeFreePropertyBlob(blob);
74d722e3fbSopenharmony_ci}
75d722e3fbSopenharmony_ci
76d722e3fbSopenharmony_cistatic void
77d722e3fbSopenharmony_cidump_prop(uint32_t prop_id, uint64_t value)
78d722e3fbSopenharmony_ci{
79d722e3fbSopenharmony_ci	int i;
80d722e3fbSopenharmony_ci	drmModePropertyPtr prop;
81d722e3fbSopenharmony_ci
82d722e3fbSopenharmony_ci	prop = drmModeGetProperty(fd, prop_id);
83d722e3fbSopenharmony_ci
84d722e3fbSopenharmony_ci	printf("\t%d", prop_id);
85d722e3fbSopenharmony_ci	if (!prop) {
86d722e3fbSopenharmony_ci		printf("\n");
87d722e3fbSopenharmony_ci		return;
88d722e3fbSopenharmony_ci	}
89d722e3fbSopenharmony_ci
90d722e3fbSopenharmony_ci	printf(" %s:\n", prop->name);
91d722e3fbSopenharmony_ci
92d722e3fbSopenharmony_ci	printf("\t\tflags:");
93d722e3fbSopenharmony_ci	if (prop->flags & DRM_MODE_PROP_PENDING)
94d722e3fbSopenharmony_ci		printf(" pending");
95d722e3fbSopenharmony_ci	if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
96d722e3fbSopenharmony_ci		printf(" immutable");
97d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
98d722e3fbSopenharmony_ci		printf(" signed range");
99d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
100d722e3fbSopenharmony_ci		printf(" range");
101d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
102d722e3fbSopenharmony_ci		printf(" enum");
103d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
104d722e3fbSopenharmony_ci		printf(" bitmask");
105d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
106d722e3fbSopenharmony_ci		printf(" blob");
107d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
108d722e3fbSopenharmony_ci		printf(" object");
109d722e3fbSopenharmony_ci	printf("\n");
110d722e3fbSopenharmony_ci
111d722e3fbSopenharmony_ci
112d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
113d722e3fbSopenharmony_ci		printf("\t\tvalues:");
114d722e3fbSopenharmony_ci		for (i = 0; i < prop->count_values; i++)
115d722e3fbSopenharmony_ci			printf(" %"PRId64, U642I64(prop->values[i]));
116d722e3fbSopenharmony_ci		printf("\n");
117d722e3fbSopenharmony_ci	}
118d722e3fbSopenharmony_ci
119d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
120d722e3fbSopenharmony_ci		printf("\t\tvalues:");
121d722e3fbSopenharmony_ci		for (i = 0; i < prop->count_values; i++)
122d722e3fbSopenharmony_ci			printf(" %"PRIu64, prop->values[i]);
123d722e3fbSopenharmony_ci		printf("\n");
124d722e3fbSopenharmony_ci	}
125d722e3fbSopenharmony_ci
126d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
127d722e3fbSopenharmony_ci		printf("\t\tenums:");
128d722e3fbSopenharmony_ci		for (i = 0; i < prop->count_enums; i++)
129d722e3fbSopenharmony_ci			printf(" %s=%"PRIu64, prop->enums[i].name,
130d722e3fbSopenharmony_ci			       (uint64_t)prop->enums[i].value);
131d722e3fbSopenharmony_ci		printf("\n");
132d722e3fbSopenharmony_ci	} else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
133d722e3fbSopenharmony_ci		printf("\t\tvalues:");
134d722e3fbSopenharmony_ci		for (i = 0; i < prop->count_enums; i++)
135d722e3fbSopenharmony_ci			printf(" %s=0x%llx", prop->enums[i].name,
136d722e3fbSopenharmony_ci			       (1LL << prop->enums[i].value));
137d722e3fbSopenharmony_ci		printf("\n");
138d722e3fbSopenharmony_ci	} else {
139d722e3fbSopenharmony_ci		assert(prop->count_enums == 0);
140d722e3fbSopenharmony_ci	}
141d722e3fbSopenharmony_ci
142d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
143d722e3fbSopenharmony_ci		printf("\t\tblobs:\n");
144d722e3fbSopenharmony_ci		for (i = 0; i < prop->count_blobs; i++)
145d722e3fbSopenharmony_ci			dump_blob(prop->blob_ids[i]);
146d722e3fbSopenharmony_ci		printf("\n");
147d722e3fbSopenharmony_ci	} else {
148d722e3fbSopenharmony_ci		assert(prop->count_blobs == 0);
149d722e3fbSopenharmony_ci	}
150d722e3fbSopenharmony_ci
151d722e3fbSopenharmony_ci	printf("\t\tvalue:");
152d722e3fbSopenharmony_ci	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
153d722e3fbSopenharmony_ci		dump_blob(value);
154d722e3fbSopenharmony_ci	else if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
155d722e3fbSopenharmony_ci		printf(" %"PRId64"\n", value);
156d722e3fbSopenharmony_ci	else
157d722e3fbSopenharmony_ci		printf(" %"PRIu64"\n", value);
158d722e3fbSopenharmony_ci
159d722e3fbSopenharmony_ci	drmModeFreeProperty(prop);
160d722e3fbSopenharmony_ci}
161d722e3fbSopenharmony_ci
162d722e3fbSopenharmony_cistatic void listObjectProperties(uint32_t id, uint32_t type)
163d722e3fbSopenharmony_ci{
164d722e3fbSopenharmony_ci	unsigned int i;
165d722e3fbSopenharmony_ci	drmModeObjectPropertiesPtr props;
166d722e3fbSopenharmony_ci
167d722e3fbSopenharmony_ci	props = drmModeObjectGetProperties(fd, id, type);
168d722e3fbSopenharmony_ci
169d722e3fbSopenharmony_ci	if (!props) {
170d722e3fbSopenharmony_ci		printf("\tNo properties: %s.\n", strerror(errno));
171d722e3fbSopenharmony_ci		return;
172d722e3fbSopenharmony_ci	}
173d722e3fbSopenharmony_ci
174d722e3fbSopenharmony_ci	for (i = 0; i < props->count_props; i++)
175d722e3fbSopenharmony_ci		dump_prop(props->props[i], props->prop_values[i]);
176d722e3fbSopenharmony_ci
177d722e3fbSopenharmony_ci	drmModeFreeObjectProperties(props);
178d722e3fbSopenharmony_ci}
179d722e3fbSopenharmony_ci
180d722e3fbSopenharmony_cistatic void listConnectorProperties(void)
181d722e3fbSopenharmony_ci{
182d722e3fbSopenharmony_ci	int i;
183d722e3fbSopenharmony_ci	drmModeConnectorPtr c;
184d722e3fbSopenharmony_ci
185d722e3fbSopenharmony_ci	for (i = 0; i < res->count_connectors; i++) {
186d722e3fbSopenharmony_ci		c = drmModeGetConnector(fd, res->connectors[i]);
187d722e3fbSopenharmony_ci
188d722e3fbSopenharmony_ci		if (!c) {
189d722e3fbSopenharmony_ci			fprintf(stderr, "Could not get connector %u: %s\n",
190d722e3fbSopenharmony_ci				res->connectors[i], strerror(errno));
191d722e3fbSopenharmony_ci			continue;
192d722e3fbSopenharmony_ci		}
193d722e3fbSopenharmony_ci
194d722e3fbSopenharmony_ci		printf("Connector %u (%s-%u)\n", c->connector_id,
195d722e3fbSopenharmony_ci		       util_lookup_connector_type_name(c->connector_type),
196d722e3fbSopenharmony_ci		       c->connector_type_id);
197d722e3fbSopenharmony_ci
198d722e3fbSopenharmony_ci		listObjectProperties(c->connector_id,
199d722e3fbSopenharmony_ci				     DRM_MODE_OBJECT_CONNECTOR);
200d722e3fbSopenharmony_ci
201d722e3fbSopenharmony_ci		drmModeFreeConnector(c);
202d722e3fbSopenharmony_ci	}
203d722e3fbSopenharmony_ci}
204d722e3fbSopenharmony_ci
205d722e3fbSopenharmony_cistatic void listCrtcProperties(void)
206d722e3fbSopenharmony_ci{
207d722e3fbSopenharmony_ci	int i;
208d722e3fbSopenharmony_ci	drmModeCrtcPtr c;
209d722e3fbSopenharmony_ci
210d722e3fbSopenharmony_ci	for (i = 0; i < res->count_crtcs; i++) {
211d722e3fbSopenharmony_ci		c = drmModeGetCrtc(fd, res->crtcs[i]);
212d722e3fbSopenharmony_ci
213d722e3fbSopenharmony_ci		if (!c) {
214d722e3fbSopenharmony_ci			fprintf(stderr, "Could not get crtc %u: %s\n",
215d722e3fbSopenharmony_ci				res->crtcs[i], strerror(errno));
216d722e3fbSopenharmony_ci			continue;
217d722e3fbSopenharmony_ci		}
218d722e3fbSopenharmony_ci
219d722e3fbSopenharmony_ci		printf("CRTC %u\n", c->crtc_id);
220d722e3fbSopenharmony_ci
221d722e3fbSopenharmony_ci		listObjectProperties(c->crtc_id, DRM_MODE_OBJECT_CRTC);
222d722e3fbSopenharmony_ci
223d722e3fbSopenharmony_ci		drmModeFreeCrtc(c);
224d722e3fbSopenharmony_ci	}
225d722e3fbSopenharmony_ci}
226d722e3fbSopenharmony_ci
227d722e3fbSopenharmony_cistatic void listAllProperties(void)
228d722e3fbSopenharmony_ci{
229d722e3fbSopenharmony_ci	listConnectorProperties();
230d722e3fbSopenharmony_ci	listCrtcProperties();
231d722e3fbSopenharmony_ci}
232d722e3fbSopenharmony_ci
233d722e3fbSopenharmony_cistatic int setProperty(char *argv[])
234d722e3fbSopenharmony_ci{
235d722e3fbSopenharmony_ci	uint32_t obj_id, obj_type, prop_id;
236d722e3fbSopenharmony_ci	uint64_t value;
237d722e3fbSopenharmony_ci
238d722e3fbSopenharmony_ci	obj_id = atoi(argv[0]);
239d722e3fbSopenharmony_ci
240d722e3fbSopenharmony_ci	if (!strcmp(argv[1], "connector")) {
241d722e3fbSopenharmony_ci		obj_type = DRM_MODE_OBJECT_CONNECTOR;
242d722e3fbSopenharmony_ci	} else if (!strcmp(argv[1], "crtc")) {
243d722e3fbSopenharmony_ci		obj_type = DRM_MODE_OBJECT_CRTC;
244d722e3fbSopenharmony_ci	} else {
245d722e3fbSopenharmony_ci		fprintf(stderr, "Invalid object type.\n");
246d722e3fbSopenharmony_ci		return 1;
247d722e3fbSopenharmony_ci	}
248d722e3fbSopenharmony_ci
249d722e3fbSopenharmony_ci	prop_id = atoi(argv[2]);
250d722e3fbSopenharmony_ci	value = atoll(argv[3]);
251d722e3fbSopenharmony_ci
252d722e3fbSopenharmony_ci	return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value);
253d722e3fbSopenharmony_ci}
254d722e3fbSopenharmony_ci
255d722e3fbSopenharmony_cistatic void usage(const char *program)
256d722e3fbSopenharmony_ci{
257d722e3fbSopenharmony_ci	printf("Usage:\n"
258d722e3fbSopenharmony_ci"  %s [options]\n"
259d722e3fbSopenharmony_ci"  %s [options] [obj id] [obj type] [prop id] [value]\n"
260d722e3fbSopenharmony_ci"\n"
261d722e3fbSopenharmony_ci"options:\n"
262d722e3fbSopenharmony_ci"  -D DEVICE  use the given device\n"
263d722e3fbSopenharmony_ci"  -M MODULE  use the given driver\n"
264d722e3fbSopenharmony_ci"\n"
265d722e3fbSopenharmony_ci"The first form just prints all the existing properties. The second one is\n"
266d722e3fbSopenharmony_ci"used to set the value of a specified property. The object type can be one of\n"
267d722e3fbSopenharmony_ci"the following strings:\n"
268d722e3fbSopenharmony_ci"  connector crtc\n"
269d722e3fbSopenharmony_ci"\n"
270d722e3fbSopenharmony_ci"Example:\n"
271d722e3fbSopenharmony_ci"  proptest 7 connector 2 1\n"
272d722e3fbSopenharmony_ci"will set property 2 of connector 7 to 1\n", program, program);
273d722e3fbSopenharmony_ci}
274d722e3fbSopenharmony_ci
275d722e3fbSopenharmony_ciint main(int argc, char *argv[])
276d722e3fbSopenharmony_ci{
277d722e3fbSopenharmony_ci	static const char optstr[] = "D:M:";
278d722e3fbSopenharmony_ci	int c, args, ret = 0;
279d722e3fbSopenharmony_ci	char *device = NULL;
280d722e3fbSopenharmony_ci	char *module = NULL;
281d722e3fbSopenharmony_ci
282d722e3fbSopenharmony_ci	while ((c = getopt(argc, argv, optstr)) != -1) {
283d722e3fbSopenharmony_ci		switch (c) {
284d722e3fbSopenharmony_ci		case 'D':
285d722e3fbSopenharmony_ci			device = optarg;
286d722e3fbSopenharmony_ci			break;
287d722e3fbSopenharmony_ci
288d722e3fbSopenharmony_ci		case 'M':
289d722e3fbSopenharmony_ci			module = optarg;
290d722e3fbSopenharmony_ci			break;
291d722e3fbSopenharmony_ci
292d722e3fbSopenharmony_ci		default:
293d722e3fbSopenharmony_ci			usage(argv[0]);
294d722e3fbSopenharmony_ci			break;
295d722e3fbSopenharmony_ci		}
296d722e3fbSopenharmony_ci	}
297d722e3fbSopenharmony_ci
298d722e3fbSopenharmony_ci	args = argc - optind;
299d722e3fbSopenharmony_ci
300d722e3fbSopenharmony_ci	fd = util_open(device, module);
301d722e3fbSopenharmony_ci	if (fd < 0)
302d722e3fbSopenharmony_ci		return 1;
303d722e3fbSopenharmony_ci
304d722e3fbSopenharmony_ci	res = drmModeGetResources(fd);
305d722e3fbSopenharmony_ci	if (!res) {
306d722e3fbSopenharmony_ci		fprintf(stderr, "Failed to get resources: %s\n",
307d722e3fbSopenharmony_ci			strerror(errno));
308d722e3fbSopenharmony_ci		ret = 1;
309d722e3fbSopenharmony_ci		goto done;
310d722e3fbSopenharmony_ci	}
311d722e3fbSopenharmony_ci
312d722e3fbSopenharmony_ci	if (args < 1) {
313d722e3fbSopenharmony_ci		listAllProperties();
314d722e3fbSopenharmony_ci	} else if (args == 4) {
315d722e3fbSopenharmony_ci		ret = setProperty(&argv[optind]);
316d722e3fbSopenharmony_ci	} else {
317d722e3fbSopenharmony_ci		usage(argv[0]);
318d722e3fbSopenharmony_ci		ret = 1;
319d722e3fbSopenharmony_ci	}
320d722e3fbSopenharmony_ci
321d722e3fbSopenharmony_ci	drmModeFreeResources(res);
322d722e3fbSopenharmony_cidone:
323d722e3fbSopenharmony_ci	drmClose(fd);
324d722e3fbSopenharmony_ci	return ret;
325d722e3fbSopenharmony_ci}
326