From: Simon Glass <simon.glass@canonical.com> Add ctx_new and ctx_dispose operations to the vidconsole interface. These allow clients to create and dispose of their own context, with the driver determining what state is stored in the context buffer. The wrapper functions provide default implementations that just initialise or free the abuf if the driver does not implement the ops. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- drivers/video/console_normal.c | 24 +++++++++++++++++ drivers/video/console_truetype.c | 23 ++++++++++++++++ drivers/video/vidconsole-uclass.c | 32 ++++++++++++++++++++++ include/video_console.h | 44 +++++++++++++++++++++++++++++++ test/dm/video.c | 22 ++++++++++++++++ 5 files changed, 145 insertions(+) diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index cfe6196fced..f6dc37bc6be 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -8,6 +8,7 @@ #include <charset.h> #include <dm.h> +#include <malloc.h> #include <spl.h> #include <video.h> #include <video_console.h> @@ -188,6 +189,27 @@ static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) return console_normal_putc_xy(dev, x_frac, y, cp); } +static int console_simple_ctx_new(struct udevice *dev, void **ctxp) +{ + struct console_ctx *ctx; + + ctx = malloc(sizeof(*ctx)); + if (!ctx) + return -ENOMEM; + + memset(ctx, '\0', sizeof(*ctx)); + *ctxp = ctx; + + return 0; +} + +static int console_simple_ctx_dispose(struct udevice *dev, void *ctx) +{ + free(ctx); + + return 0; +} + struct vidconsole_ops console_ops = { .putc_xy = console_putc_xy, .move_rows = console_move_rows, @@ -195,6 +217,8 @@ struct vidconsole_ops console_ops = { .get_font_size = console_simple_get_font_size, .get_font = console_simple_get_font, .select_font = console_simple_select_font, + .ctx_new = console_simple_ctx_new, + .ctx_dispose = console_simple_ctx_dispose, #ifdef CONFIG_CURSOR .get_cursor_info = console_get_cursor_info, .entry_save = normal_entry_save, diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index c2d165a8b8e..d707ac3c864 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -1149,6 +1149,27 @@ static int truetype_nominal(struct udevice *dev, const char *name, uint size, return 0; } +static int truetype_ctx_new(struct udevice *dev, void **ctxp) +{ + struct console_tt_ctx *ctx; + + ctx = malloc(sizeof(*ctx)); + if (!ctx) + return -ENOMEM; + + memset(ctx, '\0', sizeof(*ctx)); + *ctxp = ctx; + + return 0; +} + +static int truetype_ctx_dispose(struct udevice *dev, void *ctx) +{ + free(ctx); + + return 0; +} + static int truetype_entry_save(struct udevice *dev, struct abuf *buf) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); @@ -1331,6 +1352,8 @@ struct vidconsole_ops console_truetype_ops = { .select_font = truetype_select_font, .measure = truetype_measure, .nominal = truetype_nominal, + .ctx_new = truetype_ctx_new, + .ctx_dispose = truetype_ctx_dispose, .entry_save = truetype_entry_save, .entry_restore = truetype_entry_restore, .get_cursor_info = truetype_get_cursor_info, diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 8efe458287a..8ef9f4c90d6 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -690,6 +690,38 @@ int vidconsole_nominal(struct udevice *dev, const char *name, uint size, return 0; } +int vidconsole_ctx_new(struct udevice *dev, void **ctxp) +{ + struct vidconsole_ops *ops = vidconsole_get_ops(dev); + void *ctx; + int ret; + + if (!ops->ctx_new) + return -ENOSYS; + + ret = ops->ctx_new(dev, &ctx); + if (ret) + return ret; + *ctxp = ctx; + + return 0; +} + +int vidconsole_ctx_dispose(struct udevice *dev, void *ctx) +{ + struct vidconsole_ops *ops = vidconsole_get_ops(dev); + int ret; + + if (!ops->ctx_dispose) + return -ENOSYS; + + ret = ops->ctx_dispose(dev, ctx); + if (ret) + return ret; + + return 0; +} + int vidconsole_entry_save(struct udevice *dev, struct abuf *buf) { struct vidconsole_ops *ops = vidconsole_get_ops(dev); diff --git a/include/video_console.h b/include/video_console.h index 0acc7ab2737..adc4537ceb7 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -348,6 +348,28 @@ struct vidconsole_ops { int (*nominal)(struct udevice *dev, const char *name, uint size, uint num_chars, struct vidconsole_bbox *bbox); + /** + * ctx_new() - Create a new context for a client + * + * Allocates and initialises a context for a client of the vidconsole. + * The driver determines what information is stored in the context. + * + * @dev: Console device to use + * @ctxp: Returns new context, on success + * Return: 0 on success, -ENOMEM if out of memory + */ + int (*ctx_new)(struct udevice *dev, void **ctxp); + + /** + * ctx_dispose() - Dispose of a context + * + * Frees any memory allocated for the context. + * + * @dev: Console device to use + * @ctx: Context to dispose of + */ + int (*ctx_dispose)(struct udevice *dev, void *ctx); + /** * entry_save() - Save any text-entry information for later use * @@ -456,6 +478,28 @@ int vidconsole_measure(struct udevice *dev, const char *name, uint size, int vidconsole_nominal(struct udevice *dev, const char *name, uint size, uint num_chars, struct vidconsole_bbox *bbox); +/** + * vidconsole_ctx_new() - Create a new context for a client + * + * Allocates and initialises a context for a client of the vidconsole. + * The driver determines what information is stored in the context. + * + * @dev: Console device to use + * @ctxp: Returns new context, on success + * Return: 0 on success, -ENOMEM if out of memory + */ +int vidconsole_ctx_new(struct udevice *dev, void **ctxp); + +/** + * vidconsole_ctx_dispose() - Dispose of a context + * + * Frees any memory allocated for the context. + * + * @dev: Console device to use + * @ctx: Context to dispose of + */ +int vidconsole_ctx_dispose(struct udevice *dev, void *ctx); + /** * vidconsole_entry_save() - Save any text-entry information for later use * diff --git a/test/dm/video.c b/test/dm/video.c index 6029fa3d5cc..d802a5cc24d 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -1493,3 +1493,25 @@ static int dm_test_video_sync_damage(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_video_sync_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT); + +/* Test vidconsole context allocation */ +static int dm_test_video_context_alloc(struct unit_test_state *uts) +{ + struct udevice *dev, *con; + void *ctx; + + ut_assertok(select_vidconsole(uts, "vidconsole0")); + ut_assertok(video_get_nologo(uts, &dev)); + ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); + + ut_assertok(vidconsole_ctx_new(con, &ctx)); + ut_assertnonnull(ctx); + + ut_assertok(vidconsole_ctx_dispose(con, ctx)); + + /* Dispose should handle NULL gracefully */ + ut_assertok(vidconsole_ctx_dispose(con, NULL)); + + return 0; +} +DM_TEST(dm_test_video_context_alloc, UTF_SCAN_PDATA | UTF_SCAN_FDT); -- 2.43.0