Change expo_dump() to output object IDs in hex format. This matches the normal convention in U-Boot. Also add key_id and preview_id to the menu item dump output while we are here. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
273 lines
7.0 KiB
C
273 lines
7.0 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Dump functions for expo objects
|
|
*
|
|
* Copyright 2025 Canonical Ltd
|
|
* Written by Simon Glass <simon.glass@canonical.com>
|
|
*/
|
|
|
|
#define LOG_CATEGORY LOGC_EXPO
|
|
|
|
#include <dm.h>
|
|
#include <expo.h>
|
|
#include <mapmem.h>
|
|
#include <membuf.h>
|
|
#include <video.h>
|
|
#include "scene_internal.h"
|
|
|
|
/**
|
|
* struct dump_ctx - Context for dumping expo structures
|
|
*
|
|
* @mb: Membuf to write output to
|
|
* @scn: Current scene being dumped (or NULL if not in a scene)
|
|
* @indent: Current indentation level (number of spaces)
|
|
*/
|
|
struct dump_ctx {
|
|
struct membuf *mb;
|
|
struct scene *scn;
|
|
int indent;
|
|
};
|
|
|
|
/**
|
|
* outf() - Output a formatted string with indentation
|
|
*
|
|
* @ctx: Dump context containing membuf, scene, and indent level
|
|
* @fmt: Format string
|
|
* @...: Arguments for format string
|
|
*/
|
|
static void outf(struct dump_ctx *ctx, const char *fmt, ...)
|
|
{
|
|
char buf[256];
|
|
va_list args;
|
|
int len;
|
|
|
|
va_start(args, fmt);
|
|
membuf_printf(ctx->mb, "%*s", ctx->indent, "");
|
|
len = vsnprintf(buf, sizeof(buf), fmt, args);
|
|
membuf_put(ctx->mb, buf, len);
|
|
va_end(args);
|
|
}
|
|
|
|
static const char *obj_name(struct dump_ctx *ctx, uint id)
|
|
{
|
|
struct scene_obj *obj;
|
|
|
|
if (!id)
|
|
return "(none)";
|
|
|
|
obj = scene_obj_find(ctx->scn, id, SCENEOBJT_NONE);
|
|
if (!obj)
|
|
return "(not found)";
|
|
|
|
return obj->name;
|
|
}
|
|
|
|
static void dump_menu(struct dump_ctx *ctx, struct scene_obj_menu *menu)
|
|
{
|
|
struct scene_obj *obj = &menu->obj;
|
|
struct scene_menitem *item;
|
|
|
|
outf(ctx, "Menu: pointer_id %x title_id %x manual %d\n",
|
|
menu->pointer_id, menu->title_id,
|
|
!!(obj->flags & SCENEOF_MANUAL));
|
|
|
|
ctx->indent += 2;
|
|
list_for_each_entry(item, &menu->item_head, sibling) {
|
|
outf(ctx, "Item %x: name '%s' key_id %x label_id %x desc_id %x preview_id %x\n",
|
|
item->id, item->name, item->key_id, item->label_id,
|
|
item->desc_id, item->preview_id);
|
|
}
|
|
ctx->indent -= 2;
|
|
}
|
|
|
|
static void dump_text(struct dump_ctx *ctx, struct scene_obj_txt *txt)
|
|
{
|
|
const char *str = expo_get_str(ctx->scn->expo, txt->gen.str_id);
|
|
|
|
outf(ctx, "Text: str_id %x font_name '%s' font_size %x\n",
|
|
txt->gen.str_id,
|
|
txt->gen.font_name ? txt->gen.font_name : "(default)",
|
|
txt->gen.font_size);
|
|
ctx->indent += 2;
|
|
outf(ctx, "str '%s'\n", str ? str : "(null)");
|
|
ctx->indent -= 2;
|
|
}
|
|
|
|
static void dump_box(struct dump_ctx *ctx, struct scene_obj_box *box)
|
|
{
|
|
outf(ctx, "Box: fill %d width %x\n", box->fill, box->width);
|
|
}
|
|
|
|
static void dump_image(struct dump_ctx *ctx, struct scene_obj_img *img)
|
|
{
|
|
outf(ctx, "Image: data %lx\n", (ulong)map_to_sysmem(img->data));
|
|
}
|
|
|
|
static void dump_textline(struct dump_ctx *ctx,
|
|
struct scene_obj_textline *tline)
|
|
{
|
|
outf(ctx, "Textline: label_id %x edit_id %x\n",
|
|
tline->label_id, tline->edit_id);
|
|
ctx->indent += 2;
|
|
outf(ctx, "max_chars %x pos %x\n", tline->max_chars, tline->pos);
|
|
ctx->indent -= 2;
|
|
}
|
|
|
|
static void dump_textedit(struct dump_ctx *ctx,
|
|
struct scene_obj_txtedit *tedit)
|
|
{
|
|
outf(ctx, "Textedit: str_id %x font_name '%s' font_size %x\n",
|
|
tedit->gen.str_id,
|
|
tedit->gen.font_name ? tedit->gen.font_name : "(default)",
|
|
tedit->gen.font_size);
|
|
}
|
|
|
|
static void obj_dump_(struct dump_ctx *ctx, struct scene_obj *obj)
|
|
{
|
|
char flags_buf[256];
|
|
bool first = true;
|
|
int bit;
|
|
int pos = 0;
|
|
|
|
outf(ctx, "Object %x (%s): type %s\n", obj->id, obj->name,
|
|
scene_obj_type_name(obj->type));
|
|
ctx->indent += 2;
|
|
|
|
/* Build flags string */
|
|
for (bit = 0; bit < 16; bit++) {
|
|
uint flag = BIT(bit);
|
|
|
|
if (obj->flags & flag) {
|
|
pos += snprintf(flags_buf + pos, sizeof(flags_buf) - pos,
|
|
"%s%s", first ? "" : ", ",
|
|
scene_flag_name(flag));
|
|
first = false;
|
|
}
|
|
}
|
|
outf(ctx, "flags %s\n", pos > 0 ? flags_buf : "");
|
|
outf(ctx, "bbox: (%x,%x)-(%x,%x)\n",
|
|
obj->bbox.x0, obj->bbox.y0, obj->bbox.x1, obj->bbox.y1);
|
|
outf(ctx, "dims: %xx%x\n", obj->dims.x, obj->dims.y);
|
|
|
|
switch (obj->type) {
|
|
case SCENEOBJT_NONE:
|
|
break;
|
|
case SCENEOBJT_IMAGE:
|
|
dump_image(ctx, (struct scene_obj_img *)obj);
|
|
break;
|
|
case SCENEOBJT_TEXT:
|
|
dump_text(ctx, (struct scene_obj_txt *)obj);
|
|
break;
|
|
case SCENEOBJT_BOX:
|
|
dump_box(ctx, (struct scene_obj_box *)obj);
|
|
break;
|
|
case SCENEOBJT_MENU:
|
|
dump_menu(ctx, (struct scene_obj_menu *)obj);
|
|
break;
|
|
case SCENEOBJT_TEXTLINE:
|
|
dump_textline(ctx, (struct scene_obj_textline *)obj);
|
|
break;
|
|
case SCENEOBJT_TEXTEDIT:
|
|
dump_textedit(ctx, (struct scene_obj_txtedit *)obj);
|
|
break;
|
|
}
|
|
ctx->indent -= 2;
|
|
}
|
|
|
|
static void scene_dump_(struct dump_ctx *ctx)
|
|
{
|
|
struct scene_obj *obj;
|
|
|
|
outf(ctx, "Scene %x: name '%s'\n", ctx->scn->id, ctx->scn->name);
|
|
ctx->indent += 2;
|
|
outf(ctx, "title_id %x (%s)\n",
|
|
ctx->scn->title_id, obj_name(ctx, ctx->scn->title_id));
|
|
outf(ctx, "highlight_id %x (%s)\n",
|
|
ctx->scn->highlight_id, obj_name(ctx, ctx->scn->highlight_id));
|
|
|
|
list_for_each_entry(obj, &ctx->scn->obj_head, sibling) {
|
|
/* Skip hidden objects */
|
|
if (obj->flags & SCENEOF_HIDE)
|
|
continue;
|
|
obj_dump_(ctx, obj);
|
|
}
|
|
ctx->indent -= 2;
|
|
}
|
|
|
|
void scene_dump(struct membuf *mb, struct scene *scn, int indent)
|
|
{
|
|
struct dump_ctx ctx;
|
|
|
|
ctx.mb = mb;
|
|
ctx.scn = scn;
|
|
ctx.indent = indent;
|
|
|
|
scene_dump_(&ctx);
|
|
}
|
|
|
|
static void expo_dump_(struct dump_ctx *ctx, struct expo *exp)
|
|
{
|
|
struct scene *scn;
|
|
struct expo_theme *theme = &exp->theme;
|
|
|
|
outf(ctx, "Expo: name '%s'\n", exp->name);
|
|
ctx->indent = 2;
|
|
outf(ctx, "display %s\n",
|
|
exp->display ? exp->display->name : "(null)");
|
|
outf(ctx, "cons %s\n", exp->cons ? exp->cons->name : "(none)");
|
|
outf(ctx, "mouse %s\n", exp->mouse ? exp->mouse->name : "(none)");
|
|
outf(ctx, "scene_id %x\n", exp->scene_id);
|
|
outf(ctx, "next_id %x\n", exp->next_id);
|
|
outf(ctx, "req_width %x\n", exp->req_width);
|
|
outf(ctx, "req_height %x\n", exp->req_height);
|
|
outf(ctx, "text_mode %d\n", exp->text_mode);
|
|
outf(ctx, "popup %d\n", exp->popup);
|
|
outf(ctx, "show_highlight %d\n", exp->show_highlight);
|
|
outf(ctx, "mouse_enabled %d\n", exp->mouse_enabled);
|
|
outf(ctx, "mouse_ptr %p\n", exp->mouse_ptr);
|
|
outf(ctx, "mouse_size %xx%x\n", exp->mouse_size.w,
|
|
exp->mouse_size.h);
|
|
outf(ctx, "mouse_pos (%x,%x)\n", exp->mouse_pos.x,
|
|
exp->mouse_pos.y);
|
|
outf(ctx, "damage (%x,%x)-(%x,%x)\n", exp->damage.x0, exp->damage.y0,
|
|
exp->damage.x1, exp->damage.y1);
|
|
outf(ctx, "done %d\n", exp->done);
|
|
outf(ctx, "save %d\n", exp->save);
|
|
outf(ctx, "last_key_ms %ld\n", exp->last_key_ms);
|
|
|
|
if (exp->display) {
|
|
struct video_priv *vid_priv = dev_get_uclass_priv(exp->display);
|
|
|
|
outf(ctx, "video: %xx%x white_on_black %d\n",
|
|
vid_priv->xsize, vid_priv->ysize,
|
|
vid_priv->white_on_black);
|
|
}
|
|
|
|
outf(ctx, "Theme:\n");
|
|
ctx->indent = 4;
|
|
outf(ctx, "font_size %x\n", theme->font_size);
|
|
outf(ctx, "white_on_black %d\n", theme->white_on_black);
|
|
outf(ctx, "menu_inset %x\n", theme->menu_inset);
|
|
outf(ctx, "menuitem_gap_y %x\n", theme->menuitem_gap_y);
|
|
|
|
ctx->indent = 0;
|
|
outf(ctx, "\nScenes:\n");
|
|
ctx->indent = 2;
|
|
list_for_each_entry(scn, &exp->scene_head, sibling) {
|
|
ctx->scn = scn;
|
|
scene_dump_(ctx);
|
|
outf(ctx, "\n");
|
|
}
|
|
}
|
|
|
|
void expo_dump(struct expo *exp, struct membuf *mb)
|
|
{
|
|
struct dump_ctx ctx;
|
|
|
|
ctx.mb = mb;
|
|
ctx.scn = NULL;
|
|
ctx.indent = 0;
|
|
|
|
expo_dump_(&ctx, exp);
|
|
}
|