mirror of
https://gitlab.freedesktop.org/emersion/libdisplay-info.git
synced 2024-12-25 21:59:08 +01:00
Add a CLI tool
For now it only prints the JSON representation of the information exposed by libdisplay-info. A JSON schema [1] and libjsonschema [2] are used to encode JSON. [1]: https://json-schema.org/ [2]: https://sr.ht/~emersion/libjsonschema/ Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
parent
fc9a605611
commit
f0e5199b50
4 changed files with 223 additions and 0 deletions
|
@ -85,4 +85,5 @@ di_dep = declare_dependency(
|
||||||
meson.override_dependency('libdisplay-info', di_dep)
|
meson.override_dependency('libdisplay-info', di_dep)
|
||||||
|
|
||||||
subdir('di-edid-decode')
|
subdir('di-edid-decode')
|
||||||
|
subdir('tool')
|
||||||
subdir('test')
|
subdir('test')
|
||||||
|
|
129
tool/main.c
Normal file
129
tool/main.c
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libdisplay-info/edid.h>
|
||||||
|
#include <libdisplay-info/info.h>
|
||||||
|
|
||||||
|
#include "schema.h"
|
||||||
|
|
||||||
|
static struct edid *
|
||||||
|
get_edid(const struct di_edid *edid)
|
||||||
|
{
|
||||||
|
const struct di_edid_vendor_product *vendor_product;
|
||||||
|
char manufacturer[4];
|
||||||
|
struct edid *wire_edid;
|
||||||
|
struct edid_vendor_product *wire_vendor_product;
|
||||||
|
|
||||||
|
vendor_product = di_edid_get_vendor_product(edid);
|
||||||
|
|
||||||
|
snprintf(manufacturer, sizeof(manufacturer), "%.3s", vendor_product->manufacturer);
|
||||||
|
|
||||||
|
wire_vendor_product = malloc(sizeof(*wire_vendor_product));
|
||||||
|
*wire_vendor_product = (struct edid_vendor_product) {
|
||||||
|
.manufacturer = strdup(manufacturer),
|
||||||
|
.product = vendor_product->product,
|
||||||
|
.serial = vendor_product->serial,
|
||||||
|
.model_year = vendor_product->model_year,
|
||||||
|
.manufacture_week = vendor_product->manufacture_week,
|
||||||
|
.manufacture_year = vendor_product->manufacture_year,
|
||||||
|
};
|
||||||
|
|
||||||
|
wire_edid = malloc(sizeof(*wire_edid));
|
||||||
|
*wire_edid = (struct edid) {
|
||||||
|
.version = di_edid_get_version(edid),
|
||||||
|
.revision = di_edid_get_revision(edid),
|
||||||
|
.vendor_product = wire_vendor_product,
|
||||||
|
};
|
||||||
|
|
||||||
|
return wire_edid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct display_info *
|
||||||
|
get_info(const struct di_info *info)
|
||||||
|
{
|
||||||
|
const struct di_edid *edid;
|
||||||
|
struct edid *wire_edid = NULL;
|
||||||
|
struct display_info *wire_info;
|
||||||
|
|
||||||
|
edid = di_info_get_edid(info);
|
||||||
|
if (edid != NULL)
|
||||||
|
wire_edid = get_edid(edid);
|
||||||
|
|
||||||
|
wire_info = malloc(sizeof(*wire_info));
|
||||||
|
*wire_info = (struct display_info) {
|
||||||
|
.edid = wire_edid,
|
||||||
|
};
|
||||||
|
|
||||||
|
return wire_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char usage[] =
|
||||||
|
"usage: libdisplay-info <edid>\n";
|
||||||
|
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE *in;
|
||||||
|
static uint8_t raw[32 * 1024];
|
||||||
|
size_t size = 0;
|
||||||
|
struct di_info *info;
|
||||||
|
int opt;
|
||||||
|
struct jsch_encoder *enc;
|
||||||
|
struct display_info *wire_info;
|
||||||
|
|
||||||
|
in = stdin;
|
||||||
|
while (1) {
|
||||||
|
int option_index = 0;
|
||||||
|
opt = getopt_long(argc, argv, "h", long_options, &option_index);
|
||||||
|
if (opt == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s", usage);
|
||||||
|
return opt == 'h' ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
in = fopen(argv[1], "r");
|
||||||
|
if (!in) {
|
||||||
|
perror("failed to open input file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!feof(in)) {
|
||||||
|
size += fread(&raw[size], 1, sizeof(raw) - size, in);
|
||||||
|
if (ferror(in)) {
|
||||||
|
perror("fread failed");
|
||||||
|
return 1;
|
||||||
|
} else if (size >= sizeof(raw)) {
|
||||||
|
fprintf(stderr, "input too large\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
info = di_info_parse_edid(raw, size);
|
||||||
|
if (!info) {
|
||||||
|
perror("di_edid_parse failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wire_info = get_info(info);
|
||||||
|
|
||||||
|
enc = jsch_encoder_create(stdout);
|
||||||
|
display_info_encode(wire_info, enc);
|
||||||
|
jsch_encoder_destroy(enc);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
display_info_finish(wire_info);
|
||||||
|
free(wire_info);
|
||||||
|
di_info_destroy(info);
|
||||||
|
return 0;
|
||||||
|
}
|
40
tool/meson.build
Normal file
40
tool/meson.build
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
libjsonschema = dependency('libjsonschema')
|
||||||
|
libjsonschema_native = dependency('libjsonschema', native: true)
|
||||||
|
libjsonschema_tool_path = libjsonschema_native.get_variable(pkgconfig: 'tool', internal: 'tool')
|
||||||
|
libjsonschema_tool = find_program(libjsonschema_tool_path, native: true)
|
||||||
|
|
||||||
|
schema = files('schema.json')
|
||||||
|
|
||||||
|
schema_header = custom_target(
|
||||||
|
'schema.h',
|
||||||
|
command: [libjsonschema_tool, 'gen-header', '@INPUT@'],
|
||||||
|
input: schema,
|
||||||
|
output: 'schema.h',
|
||||||
|
capture: true,
|
||||||
|
)
|
||||||
|
|
||||||
|
schema_code = custom_target(
|
||||||
|
'schema.c',
|
||||||
|
command: [libjsonschema_tool, 'gen-code', '@INPUT@'],
|
||||||
|
input: schema,
|
||||||
|
output: 'schema.c',
|
||||||
|
capture: true,
|
||||||
|
)
|
||||||
|
|
||||||
|
schema_lib = static_library(
|
||||||
|
'schema',
|
||||||
|
schema_code,
|
||||||
|
c_args: cc.get_supported_arguments(['-Wno-declaration-after-statement']),
|
||||||
|
dependencies: libjsonschema,
|
||||||
|
)
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'libdisplay-info',
|
||||||
|
[
|
||||||
|
'main.c',
|
||||||
|
schema_header,
|
||||||
|
],
|
||||||
|
dependencies: [di_dep, libjsonschema],
|
||||||
|
link_with: schema_lib,
|
||||||
|
install: true,
|
||||||
|
)
|
53
tool/schema.json
Normal file
53
tool/schema.json
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$ref": "#/$defs/edid",
|
||||||
|
"$defs": {
|
||||||
|
"uint16": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 65535
|
||||||
|
},
|
||||||
|
"uint32": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 4294967295
|
||||||
|
},
|
||||||
|
"display_info": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"edid": { "$ref": "#/$defs/edid" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"edid": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "integer" },
|
||||||
|
"revision": { "type": "integer" },
|
||||||
|
"vendor_product": { "$ref": "#/$defs/edid_vendor_product" }
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"revision",
|
||||||
|
"vendor_product"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"edid_vendor_product": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"manufacturer": { "type": "string" },
|
||||||
|
"product": { "$ref": "#/$defs/uint16" },
|
||||||
|
"serial": { "$ref": "#/$defs/uint32" },
|
||||||
|
"model_year": { "type": "integer" },
|
||||||
|
"manufacture_week": { "type": "integer" },
|
||||||
|
"manufacture_year": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"manufacturer",
|
||||||
|
"product"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue