2018-09-25 07:56:42 +00:00
|
|
|
/*
|
|
|
|
* QEMU EDID test tool.
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qemu/bswap.h"
|
|
|
|
#include "qemu/cutils.h"
|
|
|
|
#include "hw/display/edid.h"
|
|
|
|
|
2020-10-13 09:16:15 +00:00
|
|
|
static qemu_edid_info info = {
|
2020-09-27 14:57:47 +00:00
|
|
|
.prefx = 1024,
|
|
|
|
.prefy = 768,
|
|
|
|
};
|
2018-09-25 07:56:42 +00:00
|
|
|
|
|
|
|
static void usage(FILE *out)
|
|
|
|
{
|
|
|
|
fprintf(out,
|
|
|
|
"\n"
|
|
|
|
"This is a test tool for the qemu edid generator.\n"
|
|
|
|
"\n"
|
|
|
|
"Typically you'll pipe the output into edid-decode\n"
|
|
|
|
"to check if the generator works correctly.\n"
|
|
|
|
"\n"
|
|
|
|
"usage: qemu-edid <options>\n"
|
|
|
|
"options:\n"
|
|
|
|
" -h print this text\n"
|
|
|
|
" -o <file> set output file (stdout by default)\n"
|
|
|
|
" -v <vendor> set monitor vendor (three letters)\n"
|
|
|
|
" -n <name> set monitor name\n"
|
|
|
|
" -s <serial> set monitor serial\n"
|
|
|
|
" -d <dpi> set display resolution\n"
|
|
|
|
" -x <prefx> set preferred width\n"
|
|
|
|
" -y <prefy> set preferred height\n"
|
|
|
|
" -X <maxx> set maximum width\n"
|
|
|
|
" -Y <maxy> set maximum height\n"
|
|
|
|
"\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
FILE *outfile = NULL;
|
2021-04-27 15:08:17 +00:00
|
|
|
uint8_t blob[512];
|
|
|
|
size_t size;
|
2020-09-27 14:57:47 +00:00
|
|
|
uint32_t dpi = 100;
|
2018-09-25 07:56:42 +00:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
rc = getopt(argc, argv, "ho:x:y:X:Y:d:v:n:s:");
|
|
|
|
if (rc == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (rc) {
|
|
|
|
case 'o':
|
|
|
|
if (outfile) {
|
|
|
|
fprintf(stderr, "outfile specified twice\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
outfile = fopen(optarg, "w");
|
|
|
|
if (outfile == NULL) {
|
|
|
|
fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
if (qemu_strtoui(optarg, NULL, 10, &info.prefx) < 0) {
|
|
|
|
fprintf(stderr, "not a number: %s\n", optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
if (qemu_strtoui(optarg, NULL, 10, &info.prefy) < 0) {
|
|
|
|
fprintf(stderr, "not a number: %s\n", optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
if (qemu_strtoui(optarg, NULL, 10, &info.maxx) < 0) {
|
|
|
|
fprintf(stderr, "not a number: %s\n", optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'Y':
|
|
|
|
if (qemu_strtoui(optarg, NULL, 10, &info.maxy) < 0) {
|
|
|
|
fprintf(stderr, "not a number: %s\n", optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'd':
|
2020-09-27 14:57:47 +00:00
|
|
|
if (qemu_strtoui(optarg, NULL, 10, &dpi) < 0) {
|
2018-09-25 07:56:42 +00:00
|
|
|
fprintf(stderr, "not a number: %s\n", optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
info.vendor = optarg;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
info.name = optarg;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
info.serial = optarg;
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
usage(stdout);
|
|
|
|
exit(0);
|
|
|
|
default:
|
|
|
|
usage(stderr);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outfile == NULL) {
|
|
|
|
outfile = stdout;
|
|
|
|
}
|
|
|
|
|
2020-09-27 14:57:47 +00:00
|
|
|
info.width_mm = qemu_edid_dpi_to_mm(dpi, info.prefx);
|
|
|
|
info.height_mm = qemu_edid_dpi_to_mm(dpi, info.prefy);
|
|
|
|
|
2018-09-25 07:56:42 +00:00
|
|
|
memset(blob, 0, sizeof(blob));
|
|
|
|
qemu_edid_generate(blob, sizeof(blob), &info);
|
2021-04-27 15:08:17 +00:00
|
|
|
size = qemu_edid_size(blob);
|
|
|
|
fwrite(blob, size, 1, outfile);
|
2018-09-25 07:56:42 +00:00
|
|
|
fflush(outfile);
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|