• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <math.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 
8 #include <libdisplay-info/displayid.h>
9 #include <libdisplay-info/edid.h>
10 #include <libdisplay-info/info.h>
11 
12 #include "di-edid-decode.h"
13 
14 struct uncommon_features uncommon_features = {0};
15 
16 static const struct option long_options[] = {
17 	{ "help", no_argument, 0, 'h' },
18 	{ 0, 0, 0, 0 }
19 };
20 
usage(void)21 static void usage(void)
22 {
23 	fprintf(stderr, "Usage:		di-edid-decode  <options> [in]\n"
24 			" [in]:		EDID file to parse. Read from standard input (stdin),\n"
25 			"		if none given.\n"
26 			"Example :	di-edid-decode /sys/class/drm/card0-DP-2/edid \n"
27 			"\nOptions:\n"
28 			"-h, --help	display the help message\n");
29 }
30 
31 static const char *
ext_tag_name(enum di_edid_ext_tag tag)32 ext_tag_name(enum di_edid_ext_tag tag)
33 {
34 	switch (tag) {
35 	case DI_EDID_EXT_CEA:
36 		return "CTA-861 Extension Block";
37 	case DI_EDID_EXT_VTB:
38 		return "Video Timing Extension Block";
39 	case DI_EDID_EXT_DI:
40 		return "Display Information Extension Block";
41 	case DI_EDID_EXT_LS:
42 		return "Localized String Extension Block";
43 	case DI_EDID_EXT_DPVL:
44 		return "Digital Packet Video Link Extension";
45 	case DI_EDID_EXT_BLOCK_MAP:
46 		return "Block Map Extension Block";
47 	case DI_EDID_EXT_VENDOR:
48 		return "Manufacturer-Specific Extension Block";
49 	case DI_EDID_EXT_DISPLAYID:
50 		return "DisplayID Extension Block";
51 	}
52 	abort();
53 }
54 
55 static void
print_ext(const struct di_edid_ext * ext,size_t ext_index)56 print_ext(const struct di_edid_ext *ext, size_t ext_index)
57 {
58 	const char *tag_name;
59 
60 	tag_name = ext_tag_name(di_edid_ext_get_tag(ext));
61 	printf("\n----------------\n\n");
62 	printf("Block %zu, %s:\n", ext_index + 1, tag_name);
63 
64 	switch (di_edid_ext_get_tag(ext)) {
65 	case DI_EDID_EXT_CEA:
66 		print_cta(di_edid_ext_get_cta(ext));
67 		break;
68 	case DI_EDID_EXT_DISPLAYID:
69 		print_displayid(di_edid_ext_get_displayid(ext));
70 		break;
71 	default:
72 		break; /* Ignore */
73 	}
74 }
75 
76 static size_t
edid_checksum_index(size_t block_index)77 edid_checksum_index(size_t block_index)
78 {
79 	return 128 * (block_index + 1) - 1;
80 }
81 
82 int
main(int argc,char * argv[])83 main(int argc, char *argv[])
84 {
85 	FILE *in;
86 	static uint8_t raw[32 * 1024];
87 	size_t size = 0;
88 	const struct di_edid *edid;
89 	struct di_info *info;
90 	const struct di_edid_ext *const *exts;
91 	const char *failure_msg;
92 	size_t i;
93 	int opt;
94 
95 	in = stdin;
96 	while (1) {
97 		int option_index = 0;
98 		opt = getopt_long(argc, argv, "h", long_options, &option_index);
99 		if (opt == -1)
100 			break;
101 
102 		switch (opt) {
103 		case 'h':
104 			usage();
105 			return -1;
106 		default:
107 			usage();
108 			return -1;
109 		}
110 	}
111 
112 	if (argc > 1) {
113 		in = fopen(argv[1], "r");
114 		if (!in) {
115 			perror("failed to open input file");
116 			return 1;
117 		}
118 	}
119 
120 	while (!feof(in)) {
121 		size += fread(&raw[size], 1, sizeof(raw) - size, in);
122 		if (ferror(in)) {
123 			perror("fread failed");
124 			return 1;
125 		} else if (size >= sizeof(raw)) {
126 			fprintf(stderr, "input too large\n");
127 			return 1;
128 		}
129 	}
130 
131 	fclose(in);
132 
133 	info = di_info_parse_edid(raw, size);
134 	if (!info) {
135 		perror("di_edid_parse failed");
136 		return 1;
137 	}
138 
139 	edid = di_info_get_edid(info);
140 	print_edid(edid);
141 
142 	exts = di_edid_get_extensions(edid);
143 
144 	for (i = 0; exts[i] != NULL; i++);
145 	if (i > 0) {
146 		printf("  Extension blocks: %zu\n", i);
147 	}
148 
149 	printf("Checksum: 0x%02hhx\n", raw[edid_checksum_index(0)]);
150 
151 	for (i = 0; exts[i] != NULL; i++) {
152 		print_ext(exts[i], i);
153 		printf("Checksum: 0x%02hhx\n", raw[edid_checksum_index(i + 1)]);
154 	}
155 
156 	printf("\n----------------\n\n");
157 
158 	failure_msg = di_info_get_failure_msg(info);
159 	if (failure_msg) {
160 		printf("Failures:\n\n%s", failure_msg);
161 		printf("EDID conformity: FAIL\n");
162 	} else {
163 		printf("EDID conformity: PASS\n");
164 	}
165 
166 	if (uncommon_features.color_point_descriptor) {
167 		fprintf(stderr, "The EDID blob contains an uncommon Color "
168 				"Point Descriptor. Please share the EDID blob "
169 				"with upstream!\n");
170 	}
171 	if (uncommon_features.color_management_data) {
172 		fprintf(stderr, "The EDID blob contains an uncommon Color "
173 				"Management Data Descriptor. Please share the "
174 				"EDID blob with upstream!\n");
175 	}
176 	if (uncommon_features.cta_transfer_characteristics) {
177 		fprintf(stderr, "The EDID blob contains an uncommon CTA VESA "
178 				"Display Transfer Characteristic data block. "
179 				"Please share the EDID blob with upstream!\n");
180 	}
181 
182 	di_info_destroy(info);
183 	return failure_msg ? 254 : 0;
184 }
185