1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
/*
* Rudimentary drm setup dialog... this is currently a very basic stdio thingy.
*/
#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "util.h"
static const char * encoder_type_name(uint32_t type) {
static const char *encoder_types[] = {
"None",
"DAC",
"TMDS",
"LVDAC",
"VIRTUAL",
"DSI"
};
assert(type < nelems(encoder_types));
return encoder_types[type];
}
static const char * connector_type_name(uint32_t type) {
static const char *connector_types[] = {
"Unknown",
"VGA",
"DVII",
"DVID",
"DVIA",
"Composite",
"SVIDEO",
"LVDS",
"Component",
"SPinDIN",
"DisplayPort",
"HDMIA",
"HDMIB",
"TV",
"eDP",
"VIRTUAL",
"DSI"
};
assert(type < nelems(connector_types));
return connector_types[type];
}
static const char * connection_type_name(int type) {
static const char *connection_types[] = {
[1] = "Connected",
"Disconnected",
"Unknown"
};
assert(type < nelems(connection_types));
return connection_types[type];
}
/* interactively setup the drm device, store the selections */
void drm_setup(int *res_drm_fd, uint32_t *res_crtc_id, uint32_t *res_connector_id, drmModeModeInfoPtr *res_mode)
{
int drm_fd, i, connected;
drmVersionPtr drm_ver;
drmModeResPtr drm_res;
drmModeConnectorPtr drm_con;
drmModeEncoderPtr drm_enc;
drmModeCrtcPtr drm_crtc;
char dev[256];
int connector_num, mode_num;
pexit_if(!drmAvailable(),
"drm unavailable");
ask_string(dev, sizeof(dev), "DRM device", "/dev/dri/card0");
pexit_if((drm_fd = open(dev, O_RDWR)) < 0,
"unable to open drm device \"%s\"", dev);
pexit_if(!(drm_ver = drmGetVersion(drm_fd)),
"unable to get drm version");
printf("\nVersion: %i.%i.%i\nName: \"%.*s\"\nDate: \"%.*s\"\nDescription: \"%.*s\"\n\n",
drm_ver->version_major,
drm_ver->version_minor,
drm_ver->version_patchlevel,
drm_ver->name_len,
drm_ver->name,
drm_ver->date_len,
drm_ver->date,
drm_ver->desc_len,
drm_ver->desc);
pexit_if(!(drm_res = drmModeGetResources(drm_fd)),
"unable to get drm resources");
printf("\nConnectors\n");
connected = 0;
for (i = 0; i < drm_res->count_connectors; i++) {
pexit_if(!(drm_con = drmModeGetConnector(drm_fd, drm_res->connectors[i])),
"unable to get connector %x", (int)drm_res->connectors[i]);
if (!drm_con->encoder_id) {
continue;
}
pexit_if(!(drm_enc = drmModeGetEncoder(drm_fd, drm_con->encoder_id)),
"unable to get encoder %x", (int)drm_con->encoder_id);
connected++;
printf(" %i: %s (%s%s%s)\n",
i, connector_type_name(drm_con->connector_type),
connection_type_name(drm_con->connection),
drm_con->encoder_id ? " via " : "",
drm_con->encoder_id ? encoder_type_name(drm_enc->encoder_type) : "");
/* TODO show mmWidth/mmHeight? */
}
exit_if(!connected,
"No connectors available, try different card or my bug?");
ask_num(&connector_num, drm_res->count_connectors, "Select connector", 0); // TODO default?
pexit_if(!(drm_con = drmModeGetConnector(drm_fd, drm_res->connectors[connector_num])),
"unable to get connector %x", (int)drm_res->connectors[connector_num]);
pexit_if(!(drm_enc = drmModeGetEncoder(drm_fd, drm_con->encoder_id)),
"unable to get encoder %x", (int)drm_con->encoder_id);
pexit_if(!(drm_crtc = drmModeGetCrtc(drm_fd, drm_enc->crtc_id)),
"unable to get crtc %x", (int)drm_enc->crtc_id);
*res_drm_fd = drm_fd;
*res_crtc_id = drm_crtc->crtc_id;
*res_connector_id = drm_con->connector_id;
printf("\nModes\n");
for (i = 0; i < drm_con->count_modes; i++) {
printf(" %i: %s @ %"PRIu32"Hz\n",
i, drm_con->modes[i].name,
drm_con->modes[i].vrefresh);
}
ask_num(&mode_num, drm_con->count_modes, "Select mode", 0); // TODO default to &drm_crtc->mode?
*res_mode = &drm_con->modes[mode_num];
}
|