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