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:
Simon Ser 2022-11-21 15:33:26 +01:00
parent fc9a605611
commit f0e5199b50
4 changed files with 223 additions and 0 deletions

View file

@ -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
View 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
View 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
View 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"
]
}
}
}