/* * \file modedemo.c * Test program to dump DRM kernel mode setting related information. * Queries the kernel for all available information and dumps it to stdout. * * \author Jakob Bornecrantz <wallbraker@gmail.com> */ /* * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * */ #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <unistd.h> #include <string.h> #include <inttypes.h> #include "xf86drm.h" #include "xf86drmMode.h" #include "util/common.h" int current; int connectors; int full_props; int edid; int modes; int full_modes; int encoders; int crtcs; int fbs; char *module_name; static const char* getConnectionText(drmModeConnection conn) { switch (conn) { case DRM_MODE_CONNECTED: return "connected"; case DRM_MODE_DISCONNECTED: return "disconnected"; case DRM_MODE_UNKNOWNCONNECTION: default: return "unknown"; } } static int printMode(struct drm_mode_modeinfo *mode) { if (full_modes) { printf("Mode: %s\n", mode->name); printf("\tclock : %i\n", mode->clock); printf("\thdisplay : %i\n", mode->hdisplay); printf("\thsync_start : %i\n", mode->hsync_start); printf("\thsync_end : %i\n", mode->hsync_end); printf("\thtotal : %i\n", mode->htotal); printf("\thskew : %i\n", mode->hskew); printf("\tvdisplay : %i\n", mode->vdisplay); printf("\tvsync_start : %i\n", mode->vsync_start); printf("\tvsync_end : %i\n", mode->vsync_end); printf("\tvtotal : %i\n", mode->vtotal); printf("\tvscan : %i\n", mode->vscan); printf("\tvrefresh : %i\n", mode->vrefresh); printf("\tflags : %i\n", mode->flags); } else { printf("Mode: \"%s\" %ix%i %i\n", mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh); } return 0; } static int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value) { const char *name = NULL; int j; printf("Property: %s\n", props->name); printf("\tid : %i\n", props->prop_id); printf("\tflags : %i\n", props->flags); printf("\tcount_values : %d\n", props->count_values); if (props->count_values) { printf("\tvalues :"); for (j = 0; j < props->count_values; j++) printf(" %" PRIu64, props->values[j]); printf("\n"); } printf("\tcount_enums : %d\n", props->count_enums); if (props->flags & DRM_MODE_PROP_BLOB) { drmModePropertyBlobPtr blob; blob = drmModeGetPropertyBlob(fd, value); if (blob) { printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data); drmModeFreePropertyBlob(blob); } else { printf("error getting blob %" PRIu64 "\n", value); } } else { for (j = 0; j < props->count_enums; j++) { printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name); if (props->enums[j].value == value) name = props->enums[j].name; } if (props->count_enums && name) { printf("\tcon_value : %s\n", name); } else { printf("\tcon_value : %" PRIu64 "\n", value); } } return 0; } static const char * const output_names[] = { "None", "VGA", "DVI-I", "DVI-D", "DVI-A", "Composite", "SVIDEO", "LVDS", "Component", "DIN", "DP", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", "DSI", }; static int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id) { int i = 0; struct drm_mode_modeinfo *mode = NULL; drmModePropertyPtr props; if (connector->connector_type < ARRAY_SIZE(output_names)) printf("Connector: %s-%d\n", output_names[connector->connector_type], connector->connector_type_id); else printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id); printf("\tid : %i\n", id); printf("\tencoder id : %i\n", connector->encoder_id); printf("\tconn : %s\n", getConnectionText(connector->connection)); printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight); printf("\tcount_modes : %i\n", connector->count_modes); printf("\tcount_props : %i\n", connector->count_props); if (connector->count_props) { printf("\tprops :"); for (i = 0; i < connector->count_props; i++) printf(" %i", connector->props[i]); printf("\n"); } printf("\tcount_encoders : %i\n", connector->count_encoders); if (connector->count_encoders) { printf("\tencoders :"); for (i = 0; i < connector->count_encoders; i++) printf(" %i", connector->encoders[i]); printf("\n"); } if (modes) { for (i = 0; i < connector->count_modes; i++) { mode = (struct drm_mode_modeinfo *)&connector->modes[i]; printMode(mode); } } if (full_props) { for (i = 0; i < connector->count_props; i++) { props = drmModeGetProperty(fd, connector->props[i]); if (props) { printProperty(fd, res, props, connector->prop_values[i]); drmModeFreeProperty(props); } } } return 0; } static int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id) { printf("Encoder\n"); printf("\tid :%i\n", id); printf("\tcrtc_id :%d\n", encoder->crtc_id); printf("\ttype :%d\n", encoder->encoder_type); printf("\tpossible_crtcs :0x%x\n", encoder->possible_crtcs); printf("\tpossible_clones :0x%x\n", encoder->possible_clones); return 0; } static int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id) { printf("Crtc\n"); printf("\tid : %i\n", id); printf("\tx : %i\n", crtc->x); printf("\ty : %i\n", crtc->y); printf("\twidth : %i\n", crtc->width); printf("\theight : %i\n", crtc->height); printf("\tmode : %p\n", &crtc->mode); printf("\tgamma size : %d\n", crtc->gamma_size); return 0; } static int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb) { printf("Framebuffer\n"); printf("\thandle : %i\n", fb->handle); printf("\twidth : %i\n", fb->width); printf("\theight : %i\n", fb->height); printf("\tpitch : %i\n", fb->pitch); printf("\tbpp : %i\n", fb->bpp); printf("\tdepth : %i\n", fb->depth); printf("\tbuffer_id : %i\n", fb->handle); return 0; } static int printRes(int fd, drmModeResPtr res) { int i; drmModeFBPtr fb; drmModeCrtcPtr crtc; drmModeEncoderPtr encoder; drmModeConnectorPtr connector; printf("Resources\n\n"); printf("count_connectors : %i\n", res->count_connectors); printf("count_encoders : %i\n", res->count_encoders); printf("count_crtcs : %i\n", res->count_crtcs); printf("count_fbs : %i\n", res->count_fbs); printf("\n"); if (connectors) { for (i = 0; i < res->count_connectors; i++) { connector = (current ? drmModeGetConnectorCurrent : drmModeGetConnector) (fd, res->connectors[i]); if (!connector) printf("Could not get connector %i\n", res->connectors[i]); else { printConnector(fd, res, connector, res->connectors[i]); drmModeFreeConnector(connector); } } printf("\n"); } if (encoders) { for (i = 0; i < res->count_encoders; i++) { encoder = drmModeGetEncoder(fd, res->encoders[i]); if (!encoder) printf("Could not get encoder %i\n", res->encoders[i]); else { printEncoder(fd, res, encoder, res->encoders[i]); drmModeFreeEncoder(encoder); } } printf("\n"); } if (crtcs) { for (i = 0; i < res->count_crtcs; i++) { crtc = drmModeGetCrtc(fd, res->crtcs[i]); if (!crtc) printf("Could not get crtc %i\n", res->crtcs[i]); else { printCrtc(fd, res, crtc, res->crtcs[i]); drmModeFreeCrtc(crtc); } } printf("\n"); } if (fbs) { for (i = 0; i < res->count_fbs; i++) { fb = drmModeGetFB(fd, res->fbs[i]); if (!fb) printf("Could not get fb %i\n", res->fbs[i]); else { printFrameBuffer(fd, res, fb); drmModeFreeFB(fb); } } } return 0; } static void args(int argc, char **argv) { int defaults = 1; int i; fbs = 0; edid = 0; crtcs = 0; modes = 0; encoders = 0; full_modes = 0; full_props = 0; connectors = 0; current = 0; module_name = argv[1]; for (i = 2; i < argc; i++) { if (strcmp(argv[i], "-fb") == 0) { fbs = 1; defaults = 0; } else if (strcmp(argv[i], "-crtcs") == 0) { crtcs = 1; defaults = 0; } else if (strcmp(argv[i], "-cons") == 0) { connectors = 1; modes = 1; defaults = 0; } else if (strcmp(argv[i], "-modes") == 0) { connectors = 1; modes = 1; defaults = 0; } else if (strcmp(argv[i], "-full") == 0) { connectors = 1; modes = 1; full_modes = 1; defaults = 0; } else if (strcmp(argv[i], "-props") == 0) { connectors = 1; full_props = 1; defaults = 0; } else if (strcmp(argv[i], "-edids") == 0) { connectors = 1; edid = 1; defaults = 0; } else if (strcmp(argv[i], "-encoders") == 0) { encoders = 1; defaults = 0; } else if (strcmp(argv[i], "-v") == 0) { fbs = 1; edid = 1; crtcs = 1; modes = 1; encoders = 1; full_modes = 1; full_props = 1; connectors = 1; defaults = 0; } else if (strcmp(argv[i], "-current") == 0) { current = 1; } } if (defaults) { fbs = 1; edid = 1; crtcs = 1; modes = 1; encoders = 1; full_modes = 0; full_props = 0; connectors = 1; } } int main(int argc, char **argv) { int fd; drmModeResPtr res; if (argc == 1) { printf("Please add modulename as first argument\n"); return 1; } args(argc, argv); printf("Starting test\n"); fd = drmOpen(module_name, NULL); if (fd < 0) { printf("Failed to open the card fd (%d)\n",fd); return 1; } res = drmModeGetResources(fd); if (res == 0) { printf("Failed to get resources from card\n"); drmClose(fd); return 1; } printRes(fd, res); drmModeFreeResources(res); printf("Ok\n"); return 0; }