Merge branch 'for-upstream/cherrypicker/backends-dpi' into 'master'

Allow runtime selection of the lvgl display driver ("backend"), enable DRM backend

See merge request cherrypicker/unl0kr!4
This commit is contained in:
Johannes Marbach 2022-05-21 11:02:23 +00:00
commit 2696481bbf
12 changed files with 208 additions and 18 deletions

View file

@ -14,6 +14,8 @@
- fix: Prevent scrolling when keyboard hides (#21)
- feat!: Do not show last typed character when typing (#25)
- feat: Update lvgl & lv_drivers to git master (2022-02-21)
- feat: allow runtime selection of the lvgl display driver ("backend")
- feat: allow overriding dpi with the --dpi command line parameter
## 0.1.0 (2021-11-15)

View file

@ -1,7 +1,7 @@
Unl0kr
======
Framebuffer-based disk unlocker for the initramfs based on [LVGL].
Disk unlocker for the initramfs based on [LVGL].
[[_TOC_]]
@ -72,6 +72,7 @@ Mandatory arguments to long options are mandatory for short options too.
order.
-g, --geometry=NxM Force a display size of N horizontal times M
vertical pixels
-d --dpi=N Overrides the DPI
-h, --help Print this message and exit
-v, --verbose Enable more detailed logging output on STDERR
-V, --version Print the unl0kr version and exit
@ -89,6 +90,7 @@ For an example configuration file, see [unl0kr.conf].
- [squeek2lvgl] (git submodule / linked statically)
- [libinput]
- [libxkbcommon]
- [libdrm] (optional, required for the DRM backend)
- evdev kernel module
## Building & running
@ -104,6 +106,28 @@ $ sudo ./_build/unl0kr
With meson <0\.55 use `ninja` instead of `meson compile`\.
### Optional features
If [libdrm] is installed, the DRM backend will be compiled automatically. It's possible to
change this behaviour using the `with-drm` meson feature. For example,
```
$ meson _build -Dwith-drm=disabled
```
will forcibly disable the DRM backend regardless if libdrm is installed or not.
## Backends
Unl0kr supports multiple lvgl display drivers, which are herein referred as "backends".
Currently supported backends:
- fbdev
- drm (optional)
The backend can be switched at runtime by modifying the `general.backend` configuration.
## Fonts
In order to work with [LVGL], fonts need to be converted to bitmaps, stored as C arrays. Unl0kr currently uses a combination of the [OpenSans] font for text and the [FontAwesome] font for pictograms. For both fonts only limited character ranges are included to reduce the binary size. To (re)generate the C file containing the combined font, run the following command
@ -200,6 +224,7 @@ The [FontAwesome] font is licensed under the Open Font License version 1.1.
[inih]: https://github.com/benhoyt/inih
[libinput]: https://gitlab.freedesktop.org/libinput/libinput
[libxkbcommon]: https://github.com/xkbcommon/libxkbcommon
[libdrm]: https://gitlab.freedesktop.org/mesa/drm
[lv_drivers]: https://github.com/lvgl/lv_drivers
[lv_port_linux_frame_buffer]: https://github.com/lvgl/lv_port_linux_frame_buffer
[lv_sim_emscripten]: https://github.com/lvgl/lv_sim_emscripten/blob/master/mouse_cursor_icon.c

48
backends.c Normal file
View file

@ -0,0 +1,48 @@
/**
* Copyright 2022 Eugenio Paolantonio (g7)
*
* This file is part of unl0kr, hereafter referred to as the program.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "backends.h"
#include <string.h>
/**
* Public interface
*/
const char *ul_backends_backends[] = {
#if USE_FBDEV
"fbdev",
#endif /* USE_FBDEV */
#if USE_DRM
"drm",
#endif /* USE_DRM */
NULL
};
ul_backends_backend_id_t ul_backends_find_backend_with_name(const char *name) {
for (int i = 0; ul_backends_backends[i] != NULL; ++i) {
if (strcmp(ul_backends_backends[i], name) == 0) {
ul_log(UL_LOG_LEVEL_VERBOSE, "Found backend: %s\n", name);
return i;
}
}
ul_log(UL_LOG_LEVEL_WARNING, "Backend %s not found\n", name);
return UL_BACKENDS_BACKEND_NONE;
}

50
backends.h Normal file
View file

@ -0,0 +1,50 @@
/**
* Copyright 2022 Eugenio Paolantonio (g7)
*
* This file is part of unl0kr, hereafter referred to as the program.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef UL_BACKENDS_H
#define UL_BACKENDS_H
#include "lv_drv_conf.h"
#include "log.h"
/* NOTE: Only UL_BACKENDS_BACKEND_NONE is ought to have an explicit value assigned */
typedef enum {
UL_BACKENDS_BACKEND_NONE = -1,
#if USE_FBDEV
UL_BACKENDS_BACKEND_FBDEV,
#endif /* USE_FBDEV */
#if USE_DRM
UL_BACKENDS_BACKEND_DRM,
#endif /* USE_DRM */
} ul_backends_backend_id_t;
/* Backends */
extern const char *ul_backends_backends[];
/**
* Find the first backend with a given name.
*
* @param name backend name
* @return ID of the first matching backend or UL_BACKENDS_BACKEND_NONE if no backend matched
*/
ul_backends_backend_id_t ul_backends_find_backend_with_name(const char *name);
#endif /* UL_BACKENDS_H */

View file

@ -82,6 +82,7 @@ static void print_usage() {
" order.\n"
" -g, --geometry=NxM Force a display size of N horizontal times M\n"
" vertical pixels\n"
" -d --dpi=N Overrides the DPI\n"
" -h, --help Print this message and exit\n"
" -v, --verbose Enable more detailed logging output on STDERR\n"
" -V, --version Print the unl0kr version and exit\n");
@ -100,6 +101,7 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
{ "config", required_argument, NULL, 'c' },
{ "config-override", required_argument, NULL, 'C' },
{ "geometry", required_argument, NULL, 'g' },
{ "dpi", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
@ -108,7 +110,7 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
int opt, index = 0;
while ((opt = getopt_long(argc, argv, "c:C:g:hvV", long_opts, &index)) != -1) {
while ((opt = getopt_long(argc, argv, "c:C:g:d:hvV", long_opts, &index)) != -1) {
switch (opt) {
case 'c':
opts->config_files[0] = optarg;
@ -128,6 +130,12 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
exit(EXIT_FAILURE);
}
break;
case 'd':
if (sscanf(optarg, "%i", &(opts->dpi)) != 1) {
ul_log(UL_LOG_LEVEL_ERROR, "Invalid dpi argument \"%s\"\n", optarg);
exit(EXIT_FAILURE);
}
break;
case 'h':
print_usage();
exit(EXIT_SUCCESS);

View file

@ -35,6 +35,8 @@ typedef struct {
int hor_res;
/* Vertical display resolution */
int ver_res;
/* DPI */
int dpi;
/* Verbose mode. If true, provide more detailed logging output on STDERR. */
bool verbose;
} ul_cli_opts;

View file

@ -73,6 +73,7 @@ static bool parse_bool(const char *value, bool *result);
static void init_opts(ul_config_opts *opts) {
opts->general.animations = false;
opts->general.backend = ul_backends_backends[0] == NULL ? UL_BACKENDS_BACKEND_NONE : 0;
opts->keyboard.autohide = true;
opts->keyboard.layout_id = SQ2LV_LAYOUT_US;
opts->keyboard.popovers = false;
@ -95,6 +96,12 @@ static int parsing_handler(void* user_data, const char* section, const char* key
if (parse_bool(value, &(opts->general.animations))) {
return 1;
}
} else if (strcmp(key, "backend") == 0) {
ul_backends_backend_id_t id = ul_backends_find_backend_with_name(value);
if (id != UL_BACKENDS_BACKEND_NONE) {
opts->general.backend = id;
return 1;
}
}
} else if (strcmp(section, "keyboard") == 0) {
if (strcmp(key, "autohide") == 0) {

View file

@ -21,6 +21,8 @@
#ifndef UL_CONFIG_H
#define UL_CONFIG_H
#include "backends.h"
#include "themes.h"
#include "sq2lv_layouts.h"
@ -31,6 +33,8 @@
* General options
*/
typedef struct {
/* Backend to use */
ul_backends_backend_id_t backend;
/* If true, use animations */
bool animations;
} ul_config_opts_general;

53
main.c
View file

@ -18,6 +18,7 @@
*/
#include "backends.h"
#include "command_line.h"
#include "config.h"
#include "indev.h"
@ -27,7 +28,14 @@
#include "theme.h"
#include "themes.h"
#include "lv_drv_conf.h"
#if USE_FBDEV
#include "lv_drivers/display/fbdev.h"
#endif /* USE_FBDEV */
#if USE_DRM
#include "lv_drivers/display/drm.h"
#endif /* USE_DRM */
#include "lvgl/lvgl.h"
@ -338,19 +346,45 @@ int main(int argc, char *argv[]) {
lv_init();
lv_log_register_print_cb(ul_log_print_cb);
/* Initialise framebuffer driver and query display size */
fbdev_init();
uint32_t hor_res;
uint32_t ver_res;
fbdev_get_sizes(&hor_res, &ver_res);
/* Initialise display driver */
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
/* Override display size with command line options if necessary */
/* Initialise framebuffer driver and query display size */
uint32_t hor_res = 0;
uint32_t ver_res = 0;
uint32_t dpi = 0;
switch (conf_opts.general.backend) {
#if USE_FBDEV
case UL_BACKENDS_BACKEND_FBDEV:
fbdev_init();
fbdev_get_sizes(&hor_res, &ver_res);
disp_drv.flush_cb = fbdev_flush;
break;
#endif /* USE_FBDEV */
#if USE_DRM
case UL_BACKENDS_BACKEND_DRM:
drm_init();
drm_get_sizes((lv_coord_t *)&hor_res, (lv_coord_t *)&ver_res, &dpi);
disp_drv.flush_cb = drm_flush;
break;
#endif /* USE_DRM */
default:
ul_log(UL_LOG_LEVEL_ERROR, "Unable to find suitable backend");
exit(EXIT_FAILURE);
}
/* Override display parameters with command line options if necessary */
if (cli_opts.hor_res > 0) {
hor_res = LV_MIN(hor_res, cli_opts.hor_res);
}
if (cli_opts.ver_res > 0) {
ver_res = LV_MIN(ver_res, cli_opts.ver_res);
}
if (cli_opts.dpi > 0) {
dpi = cli_opts.dpi;
}
/* Prepare display buffer */
const size_t buf_size = hor_res * ver_res / 10; /* At least 1/10 of the display size is recommended */
@ -358,13 +392,12 @@ int main(int argc, char *argv[]) {
lv_color_t *buf = (lv_color_t *)malloc(buf_size * sizeof(lv_color_t));
lv_disp_draw_buf_init(&disp_buf, buf, NULL, buf_size);
/* Initialise display driver */
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
/* Register display driver */
disp_drv.draw_buf = &disp_buf;
disp_drv.flush_cb = fbdev_flush;
disp_drv.hor_res = hor_res;
disp_drv.ver_res = ver_res;
disp_drv.dpi = dpi;
lv_disp_drv_register(&disp_drv);
/* Connect input devices */

View file

@ -27,6 +27,7 @@ project(
add_project_arguments('-DUL_VERSION="@0@"'.format(meson.project_version()), language: ['c'])
unl0kr_sources = [
'backends.c',
'command_line.c',
'config.c',
'cursor.c',
@ -37,13 +38,25 @@ unl0kr_sources = [
'sq2lv_layouts.c',
'terminal.c',
'theme.c',
'themes.c'
'themes.c',
]
squeek2lvgl_sources = [
'squeek2lvgl/sq2lv.c',
]
unl0kr_dependencies = [
dependency('inih'),
dependency('libinput'),
dependency('xkbcommon'),
]
libdrm_dep = dependency('libdrm', required: get_option('with-drm'))
if libdrm_dep.found()
unl0kr_dependencies += [libdrm_dep]
add_project_arguments('-DUSE_DRM=1', language: ['c'])
endif
lvgl_sources = run_command('find-lvgl-sources.sh', 'lvgl', check: true).stdout().strip().split('\n')
lv_drivers_sources = run_command('find-lvgl-sources.sh', 'lv_drivers', check: true).stdout().strip().split('\n')
@ -54,10 +67,6 @@ executable(
'unl0kr',
sources: unl0kr_sources + squeek2lvgl_sources + lvgl_sources + lv_drivers_sources,
include_directories: ['lvgl', 'lv_drivers'],
dependencies: [
dependency('inih'),
dependency('libinput'),
dependency('xkbcommon')
],
dependencies: unl0kr_dependencies,
install: true
)

1
meson_options.txt Normal file
View file

@ -0,0 +1 @@
option('with-drm', type : 'feature', value : 'auto', description : 'Enable DRM backend')

View file

@ -1,5 +1,6 @@
[general]
animations=true
#backend=fbdev
[keyboard]
autohide=true