13f012e29Smrg/* 23f012e29Smrg * Copyright 2008 Tungsten Graphics 33f012e29Smrg * Jakob Bornecrantz <jakob@tungstengraphics.com> 43f012e29Smrg * Copyright 2008 Intel Corporation 53f012e29Smrg * Jesse Barnes <jesse.barnes@intel.com> 63f012e29Smrg * 73f012e29Smrg * Permission is hereby granted, free of charge, to any person obtaining a 83f012e29Smrg * copy of this software and associated documentation files (the "Software"), 93f012e29Smrg * to deal in the Software without restriction, including without limitation 103f012e29Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 113f012e29Smrg * and/or sell copies of the Software, and to permit persons to whom the 123f012e29Smrg * Software is furnished to do so, subject to the following conditions: 133f012e29Smrg * 143f012e29Smrg * The above copyright notice and this permission notice shall be included in 153f012e29Smrg * all copies or substantial portions of the Software. 163f012e29Smrg * 173f012e29Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 183f012e29Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 193f012e29Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 203f012e29Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 213f012e29Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 223f012e29Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 233f012e29Smrg * IN THE SOFTWARE. 243f012e29Smrg */ 253f012e29Smrg 263f012e29Smrg/* 273f012e29Smrg * This fairly simple test program dumps output in a similar format to the 283f012e29Smrg * "xrandr" tool everyone knows & loves. It's necessarily slightly different 293f012e29Smrg * since the kernel separates outputs into encoder and connector structures, 303f012e29Smrg * each with their own unique ID. The program also allows test testing of the 313f012e29Smrg * memory management and mode setting APIs by allowing the user to specify a 323f012e29Smrg * connector and mode to use for mode setting. If all works as expected, a 333f012e29Smrg * blue background should be painted on the monitor attached to the specified 343f012e29Smrg * connector after the selected mode is set. 353f012e29Smrg * 363f012e29Smrg * TODO: use cairo to write the mode info on the selected output once 373f012e29Smrg * the mode has been programmed, along with possible test patterns. 383f012e29Smrg */ 393f012e29Smrg 403f012e29Smrg#include <errno.h> 413f012e29Smrg#include <stdint.h> 423f012e29Smrg#include <stdio.h> 433f012e29Smrg#include <stdlib.h> 443f012e29Smrg#include <string.h> 456acbc0e0Smrg#include <fcntl.h> 466acbc0e0Smrg#include <unistd.h> 473f012e29Smrg 483f012e29Smrg#include "xf86drm.h" 493f012e29Smrg#include "xf86drmMode.h" 503f012e29Smrg 513f012e29Smrg#include "common.h" 523f012e29Smrg 533f012e29Smrgstruct type_name { 543f012e29Smrg unsigned int type; 553f012e29Smrg const char *name; 563f012e29Smrg}; 573f012e29Smrg 583f012e29Smrgstatic const char *util_lookup_type_name(unsigned int type, 593f012e29Smrg const struct type_name *table, 603f012e29Smrg unsigned int count) 613f012e29Smrg{ 623f012e29Smrg unsigned int i; 633f012e29Smrg 643f012e29Smrg for (i = 0; i < count; i++) 653f012e29Smrg if (table[i].type == type) 663f012e29Smrg return table[i].name; 673f012e29Smrg 683f012e29Smrg return NULL; 693f012e29Smrg} 703f012e29Smrg 713f012e29Smrgstatic const struct type_name encoder_type_names[] = { 723f012e29Smrg { DRM_MODE_ENCODER_NONE, "none" }, 733f012e29Smrg { DRM_MODE_ENCODER_DAC, "DAC" }, 743f012e29Smrg { DRM_MODE_ENCODER_TMDS, "TMDS" }, 753f012e29Smrg { DRM_MODE_ENCODER_LVDS, "LVDS" }, 763f012e29Smrg { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, 773f012e29Smrg { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, 783f012e29Smrg { DRM_MODE_ENCODER_DSI, "DSI" }, 793f012e29Smrg { DRM_MODE_ENCODER_DPMST, "DPMST" }, 80d8807b2fSmrg { DRM_MODE_ENCODER_DPI, "DPI" }, 813f012e29Smrg}; 823f012e29Smrg 833f012e29Smrgconst char *util_lookup_encoder_type_name(unsigned int type) 843f012e29Smrg{ 853f012e29Smrg return util_lookup_type_name(type, encoder_type_names, 863f012e29Smrg ARRAY_SIZE(encoder_type_names)); 873f012e29Smrg} 883f012e29Smrg 893f012e29Smrgstatic const struct type_name connector_status_names[] = { 903f012e29Smrg { DRM_MODE_CONNECTED, "connected" }, 913f012e29Smrg { DRM_MODE_DISCONNECTED, "disconnected" }, 923f012e29Smrg { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, 933f012e29Smrg}; 943f012e29Smrg 953f012e29Smrgconst char *util_lookup_connector_status_name(unsigned int status) 963f012e29Smrg{ 973f012e29Smrg return util_lookup_type_name(status, connector_status_names, 983f012e29Smrg ARRAY_SIZE(connector_status_names)); 993f012e29Smrg} 1003f012e29Smrg 1013f012e29Smrgint util_open(const char *device, const char *module) 1023f012e29Smrg{ 1036acbc0e0Smrg int fd = -1; 1046acbc0e0Smrg drmVersionPtr version; 1053f012e29Smrg 1066acbc0e0Smrg if (module || device) { 1073f012e29Smrg fd = drmOpen(module, device); 1083f012e29Smrg if (fd < 0) { 1096acbc0e0Smrg fprintf(stderr, "failed to open device '%s' with busid '%s': %s\n", 1106acbc0e0Smrg module, device, strerror(errno)); 1113f012e29Smrg return -errno; 1123f012e29Smrg } 1133f012e29Smrg } else { 1143f012e29Smrg unsigned int i; 1156acbc0e0Smrg drmDevicePtr devices[64]; 1166acbc0e0Smrg int num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); 1176acbc0e0Smrg if (num_devices < 0) { 1186acbc0e0Smrg fprintf(stderr, "drmGetDevices2() failed with %s\n", strerror(num_devices)); 1196acbc0e0Smrg return num_devices; 1206acbc0e0Smrg } 1213f012e29Smrg 1226acbc0e0Smrg for (i = 0; i < num_devices; i++) { 1236acbc0e0Smrg drmDevicePtr device = devices[i]; 1246acbc0e0Smrg // Select only primary nodes 1256acbc0e0Smrg if ((device->available_nodes & 1 << DRM_NODE_PRIMARY) == 0) 1266acbc0e0Smrg continue; 1276acbc0e0Smrg 1286acbc0e0Smrg printf("trying to open device '%s'... ", device->nodes[DRM_NODE_PRIMARY]); 1296acbc0e0Smrg fd = open(device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC); 1303f012e29Smrg 1313f012e29Smrg if (fd < 0) { 1323f012e29Smrg printf("failed\n"); 1336acbc0e0Smrg } else if (!drmIsKMS(fd)) { 1346acbc0e0Smrg printf("is not a KMS device\n"); 1356acbc0e0Smrg close(fd); 1366acbc0e0Smrg fd = -1; 1373f012e29Smrg } else { 1383f012e29Smrg printf("done\n"); 1393f012e29Smrg break; 1403f012e29Smrg } 1413f012e29Smrg } 1423f012e29Smrg 1433f012e29Smrg if (fd < 0) { 1443f012e29Smrg fprintf(stderr, "no device found\n"); 1453f012e29Smrg return -ENODEV; 1463f012e29Smrg } 1473f012e29Smrg } 1483f012e29Smrg 1496acbc0e0Smrg version = drmGetVersion(fd); 1506acbc0e0Smrg printf("opened device `%s` on driver `%s` (version %d.%d.%d at %s)\n", 1516acbc0e0Smrg version->desc, 1526acbc0e0Smrg version->name, 1536acbc0e0Smrg version->version_major, 1546acbc0e0Smrg version->version_minor, 1556acbc0e0Smrg version->version_patchlevel, 1566acbc0e0Smrg version->date); 1576acbc0e0Smrg drmFreeVersion(version); 1586acbc0e0Smrg 1593f012e29Smrg return fd; 1603f012e29Smrg} 161