1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * Copyright 2022 Google LLC 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7#ifndef __EXPO_H 8#define __EXPO_H 9 10#include <abuf.h> 11#include <dm/ofnode_decl.h> 12#include <linux/list.h> 13 14struct udevice; 15 16#include <cli.h> 17 18/** 19 * enum expoact_type - types of actions reported by the expo 20 * 21 * @EXPOACT_NONE: no action 22 * @EXPOACT_POINT_OBJ: object was highlighted (@id indicates which) 23 * @EXPOACT_POINT_ITEM: menu item was highlighted (@id indicates which) 24 * @EXPOACT_SELECT: menu item was selected (@id indicates which) 25 * @EXPOACT_OPEN: menu was opened, so an item can be selected (@id indicates 26 * which menu object) 27 * @EXPOACT_CLOSE: menu was closed (@id indicates which menu object) 28 * @EXPOACT_QUIT: request to exit the menu 29 */ 30enum expoact_type { 31 EXPOACT_NONE, 32 EXPOACT_POINT_OBJ, 33 EXPOACT_POINT_ITEM, 34 EXPOACT_SELECT, 35 EXPOACT_OPEN, 36 EXPOACT_CLOSE, 37 EXPOACT_QUIT, 38}; 39 40/** 41 * struct expo_action - an action report by the expo 42 * 43 * @type: Action type (EXPOACT_NONE if there is no action) 44 * @select: Used for EXPOACT_POINT_ITEM and EXPOACT_SELECT 45 * @id: ID number of the object affected. 46 */ 47struct expo_action { 48 enum expoact_type type; 49 union { 50 struct { 51 int id; 52 } select; 53 }; 54}; 55 56/** 57 * struct expo_theme - theme for the expo 58 * 59 * @font_size: Default font size for all text 60 * @menu_inset: Inset width (on each side and top/bottom) for menu items 61 * @menuitem_gap_y: Gap between menu items in pixels 62 */ 63struct expo_theme { 64 u32 font_size; 65 u32 menu_inset; 66 u32 menuitem_gap_y; 67}; 68 69/** 70 * struct expo - information about an expo 71 * 72 * A group of scenes which can be presented to the user, typically to obtain 73 * input or to make a selection. 74 * 75 * @name: Name of the expo (allocated) 76 * @display: Display to use (`UCLASS_VIDEO`), or NULL to use text mode 77 * @cons: Console to use (`UCLASS_VIDEO_CONSOLE`), or NULL to use text mode 78 * @scene_id: Current scene ID (0 if none) 79 * @next_id: Next ID number to use, for automatic allocation 80 * @action: Action selected by user. At present only one is supported, with the 81 * type set to EXPOACT_NONE if there is no action 82 * @text_mode: true to use text mode for the menu (no vidconsole) 83 * @popup: true to use popup menus, instead of showing all items 84 * @priv: Private data for the controller 85 * @theme: Information about fonts styles, etc. 86 * @scene_head: List of scenes 87 * @str_head: list of strings 88 */ 89struct expo { 90 char *name; 91 struct udevice *display; 92 struct udevice *cons; 93 uint scene_id; 94 uint next_id; 95 struct expo_action action; 96 bool text_mode; 97 bool popup; 98 void *priv; 99 struct expo_theme theme; 100 struct list_head scene_head; 101 struct list_head str_head; 102}; 103 104/** 105 * struct expo_string - a string that can be used in an expo 106 * 107 * @id: ID number of the string 108 * @str: String 109 * @sibling: Node to link this object to its siblings 110 */ 111struct expo_string { 112 uint id; 113 const char *str; 114 struct list_head sibling; 115}; 116 117/** 118 * struct scene - information about a scene in an expo 119 * 120 * A collection of text/image/menu items in an expo 121 * 122 * @expo: Expo this scene is part of 123 * @name: Name of the scene (allocated) 124 * @id: ID number of the scene 125 * @title_id: String ID of title of the scene (allocated) 126 * @highlight_id: ID of highlighted object, if any 127 * @cls: cread state to use for input 128 * @buf: Buffer for input 129 * @entry_save: Buffer to hold vidconsole text-entry information 130 * @sibling: Node to link this scene to its siblings 131 * @obj_head: List of objects in the scene 132 */ 133struct scene { 134 struct expo *expo; 135 char *name; 136 uint id; 137 uint title_id; 138 uint highlight_id; 139 struct cli_line_state cls; 140 struct abuf buf; 141 struct abuf entry_save; 142 struct list_head sibling; 143 struct list_head obj_head; 144}; 145 146/** 147 * enum scene_obj_t - type of a scene object 148 * 149 * @SCENEOBJT_NONE: Used to indicate that the type does not matter 150 * @SCENEOBJT_IMAGE: Image data to render 151 * @SCENEOBJT_TEXT: Text line to render 152 * @SCENEOBJT_MENU: Menu containing items the user can select 153 * @SCENEOBJT_TEXTLINE: Line of text the user can edit 154 */ 155enum scene_obj_t { 156 SCENEOBJT_NONE = 0, 157 SCENEOBJT_IMAGE, 158 SCENEOBJT_TEXT, 159 160 /* types from here on can be highlighted */ 161 SCENEOBJT_MENU, 162 SCENEOBJT_TEXTLINE, 163}; 164 165/** 166 * struct scene_dim - Dimensions of an object 167 * 168 * @x: x position, in pixels from left side 169 * @y: y position, in pixels from top 170 * @w: width, in pixels 171 * @h: height, in pixels 172 */ 173struct scene_dim { 174 int x; 175 int y; 176 int w; 177 int h; 178}; 179 180/** 181 * enum scene_obj_flags_t - flags for objects 182 * 183 * @SCENEOF_HIDE: object should be hidden 184 * @SCENEOF_POINT: object should be highlighted 185 * @SCENEOF_OPEN: object should be opened (e.g. menu is opened so that an option 186 * can be selected) 187 */ 188enum scene_obj_flags_t { 189 SCENEOF_HIDE = 1 << 0, 190 SCENEOF_POINT = 1 << 1, 191 SCENEOF_OPEN = 1 << 2, 192}; 193 194enum { 195 /* Maximum number of characters allowed in an line editor */ 196 EXPO_MAX_CHARS = 250, 197}; 198 199/** 200 * struct scene_obj - information about an object in a scene 201 * 202 * @scene: Scene that this object relates to 203 * @name: Name of the object (allocated) 204 * @id: ID number of the object 205 * @type: Type of this object 206 * @dim: Dimensions for this object 207 * @flags: Flags for this object 208 * @bit_length: Number of bits used for this object in CMOS RAM 209 * @start_bit: Start bit to use for this object in CMOS RAM 210 * @sibling: Node to link this object to its siblings 211 */ 212struct scene_obj { 213 struct scene *scene; 214 char *name; 215 uint id; 216 enum scene_obj_t type; 217 struct scene_dim dim; 218 u8 flags; 219 u8 bit_length; 220 u16 start_bit; 221 struct list_head sibling; 222}; 223 224/* object can be highlighted when moving around expo */ 225static inline bool scene_obj_can_highlight(const struct scene_obj *obj) 226{ 227 return obj->type >= SCENEOBJT_MENU; 228} 229 230/** 231 * struct scene_obj_img - information about an image object in a scene 232 * 233 * This is a rectangular image which is blitted onto the display 234 * 235 * @obj: Basic object information 236 * @data: Image data in BMP format 237 */ 238struct scene_obj_img { 239 struct scene_obj obj; 240 char *data; 241}; 242 243/** 244 * struct scene_obj_txt - information about a text object in a scene 245 * 246 * This is a single-line text object 247 * 248 * @obj: Basic object information 249 * @str_id: ID of the text string to display 250 * @font_name: Name of font (allocated by caller) 251 * @font_size: Nominal size of font in pixels 252 */ 253struct scene_obj_txt { 254 struct scene_obj obj; 255 uint str_id; 256 const char *font_name; 257 uint font_size; 258}; 259 260/** 261 * struct scene_obj_menu - information about a menu object in a scene 262 * 263 * A menu has a number of items which can be selected by the user 264 * 265 * It also has: 266 * 267 * - a text/image object (@pointer_id) which points to the current item 268 * (@cur_item_id) 269 * 270 * - a preview object which shows an image related to the current item 271 * 272 * @obj: Basic object information 273 * @title_id: ID of the title text, or 0 if none 274 * @cur_item_id: ID of the current menu item, or 0 if none 275 * @pointer_id: ID of the object pointing to the current selection 276 * @item_head: List of items in the menu 277 */ 278struct scene_obj_menu { 279 struct scene_obj obj; 280 uint title_id; 281 uint cur_item_id; 282 uint pointer_id; 283 struct list_head item_head; 284}; 285 286/** 287 * enum scene_menuitem_flags_t - flags for menu items 288 * 289 * @SCENEMIF_GAP_BEFORE: Add a gap before this item 290 */ 291enum scene_menuitem_flags_t { 292 SCENEMIF_GAP_BEFORE = 1 << 0, 293}; 294 295/** 296 * struct scene_menitem - a menu item in a menu 297 * 298 * A menu item has: 299 * 300 * - text object holding the name (short) and description (can be longer) 301 * - a text object holding the keypress 302 * 303 * @name: Name of the item (this is allocated by this call) 304 * @id: ID number of the object 305 * @key_id: ID of text object to use as the keypress to show 306 * @label_id: ID of text object to use as the label text 307 * @desc_id: ID of text object to use as the description text 308 * @preview_id: ID of the preview object, or 0 if none 309 * @flags: Flags for this item 310 * @sibling: Node to link this item to its siblings 311 */ 312struct scene_menitem { 313 char *name; 314 uint id; 315 uint key_id; 316 uint label_id; 317 uint desc_id; 318 uint preview_id; 319 uint flags; 320 struct list_head sibling; 321}; 322 323/** 324 * struct scene_obj_textline - information about a textline in a scene 325 * 326 * A textline has a prompt and a line of editable text 327 * 328 * @obj: Basic object information 329 * @label_id: ID of the label text, or 0 if none 330 * @edit_id: ID of the editable text 331 * @max_chars: Maximum number of characters allowed 332 * @buf: Text buffer containing current text 333 * @pos: Cursor position 334 */ 335struct scene_obj_textline { 336 struct scene_obj obj; 337 uint label_id; 338 uint edit_id; 339 uint max_chars; 340 struct abuf buf; 341 uint pos; 342}; 343 344/** 345 * expo_new() - create a new expo 346 * 347 * Allocates a new expo 348 * 349 * @name: Name of expo (this is allocated by this call) 350 * @priv: Private data for the controller 351 * @expp: Returns a pointer to the new expo on success 352 * Returns: 0 if OK, -ENOMEM if out of memory 353 */ 354int expo_new(const char *name, void *priv, struct expo **expp); 355 356/** 357 * expo_destroy() - Destroy an expo and free all its memory 358 * 359 * @exp: Expo to destroy 360 */ 361void expo_destroy(struct expo *exp); 362 363/** 364 * expo_set_dynamic_start() - Set the start of the 'dynamic' IDs 365 * 366 * It is common for a set of 'static' IDs to be used to refer to objects in the 367 * expo. These typically use an enum so that they are defined in sequential 368 * order. 369 * 370 * Dynamic IDs (for objects not in the enum) are intended to be used for 371 * objects to which the code does not need to refer. These are ideally located 372 * above the static IDs. 373 * 374 * Use this function to set the start of the dynamic range, making sure that the 375 * value is higher than all the statically allocated IDs. 376 * 377 * @exp: Expo to update 378 * @dyn_start: Start ID that expo should use for dynamic allocation 379 */ 380void expo_set_dynamic_start(struct expo *exp, uint dyn_start); 381 382/** 383 * expo_str() - add a new string to an expo 384 * 385 * @exp: Expo to update 386 * @name: Name to use (this is allocated by this call) 387 * @id: ID to use for the new object (0 to allocate one) 388 * @str: Pointer to text to display (allocated by caller) 389 * Returns: ID number for the object (typically @id), or -ve on error 390 */ 391int expo_str(struct expo *exp, const char *name, uint id, const char *str); 392 393/** 394 * expo_get_str() - Get a string by ID 395 * 396 * @exp: Expo to use 397 * @id: String ID to look up 398 * @returns string, or NULL if not found 399 */ 400const char *expo_get_str(struct expo *exp, uint id); 401 402/** 403 * expo_set_display() - set the display to use for a expo 404 * 405 * @exp: Expo to update 406 * @dev: Display to use (`UCLASS_VIDEO`), NULL to use text mode 407 * Returns: 0 (always) 408 */ 409int expo_set_display(struct expo *exp, struct udevice *dev); 410 411/** 412 * expo_calc_dims() - Calculate the dimensions of the objects 413 * 414 * Updates the width and height of all objects based on their contents 415 * 416 * @exp: Expo to update 417 * Returns 0 if OK, -ENOTSUPP if there is no graphical console 418 */ 419int expo_calc_dims(struct expo *exp); 420 421/** 422 * expo_set_scene_id() - Set the current scene ID 423 * 424 * @exp: Expo to update 425 * @scene_id: New scene ID to use (0 to select no scene) 426 * Returns: 0 if OK, -ENOENT if there is no scene with that ID 427 */ 428int expo_set_scene_id(struct expo *exp, uint scene_id); 429 430/** 431 * expo_first_scene_id() - Get the ID of the first scene 432 * 433 * @exp: Expo to check 434 * Returns: Scene ID of first scene, or -ENOENT if there are no scenes 435 */ 436int expo_first_scene_id(struct expo *exp); 437 438/** 439 * expo_render() - render the expo on the display / console 440 * 441 * @exp: Expo to render 442 * 443 * Returns: 0 if OK, -ECHILD if there is no current scene, -ENOENT if the 444 * current scene is not found, other error if something else goes wrong 445 */ 446int expo_render(struct expo *exp); 447 448/** 449 * expo_set_text_mode() - Controls whether the expo renders in text mode 450 * 451 * @exp: Expo to update 452 * @text_mode: true to use text mode, false to use the console 453 */ 454void expo_set_text_mode(struct expo *exp, bool text_mode); 455 456/** 457 * scene_new() - create a new scene in a expo 458 * 459 * The scene is given the ID @id which must be unique across all scenes, objects 460 * and items. The expo's @next_id is updated to at least @id + 1 461 * 462 * @exp: Expo to update 463 * @name: Name to use (this is allocated by this call) 464 * @id: ID to use for the new scene (0 to allocate one) 465 * @scnp: Returns a pointer to the new scene on success 466 * Returns: ID number for the scene (typically @id), or -ve on error 467 */ 468int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp); 469 470/** 471 * expo_lookup_scene_id() - Look up a scene by ID 472 * 473 * @exp: Expo to check 474 * @scene_id: Scene ID to look up 475 * @returns pointer to scene if found, else NULL 476 */ 477struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); 478 479/** 480 * scene_highlight_first() - Highlight the first item in a scene 481 * 482 * This highlights the first item, so that the user can see that it is pointed 483 * to 484 * 485 * @scn: Scene to update 486 */ 487void scene_highlight_first(struct scene *scn); 488 489/** 490 * scene_set_highlight_id() - Set the object which is highlighted 491 * 492 * Sets a new object to highlight in the scene 493 * 494 * @scn: Scene to update 495 * @id: ID of object to highlight 496 */ 497void scene_set_highlight_id(struct scene *scn, uint id); 498 499/** 500 * scene_set_open() - Set whether an item is open or not 501 * 502 * @scn: Scene to update 503 * @id: ID of object to update 504 * @open: true to open the object, false to close it 505 * Returns: 0 if OK, -ENOENT if @id is invalid 506 */ 507int scene_set_open(struct scene *scn, uint id, bool open); 508 509/** 510 * scene_title_set() - set the scene title 511 * 512 * @scn: Scene to update 513 * @title_id: Title ID to set 514 * Returns: 0 if OK 515 */ 516int scene_title_set(struct scene *scn, uint title_id); 517 518/** 519 * scene_obj_count() - Count the number of objects in a scene 520 * 521 * @scn: Scene to check 522 * Returns: number of objects in the scene, 0 if none 523 */ 524int scene_obj_count(struct scene *scn); 525 526/** 527 * scene_img() - add a new image to a scene 528 * 529 * @scn: Scene to update 530 * @name: Name to use (this is allocated by this call) 531 * @id: ID to use for the new object (0 to allocate one) 532 * @data: Pointer to image data 533 * @imgp: If non-NULL, returns the new object 534 * Returns: ID number for the object (typically @id), or -ve on error 535 */ 536int scene_img(struct scene *scn, const char *name, uint id, char *data, 537 struct scene_obj_img **imgp); 538 539/** 540 * scene_txt() - add a new text object to a scene 541 * 542 * @scn: Scene to update 543 * @name: Name to use (this is allocated by this call) 544 * @id: ID to use for the new object (0 to allocate one) 545 * @str_id: ID of the string to use 546 * @txtp: If non-NULL, returns the new object 547 * Returns: ID number for the object (typically @id), or -ve on error 548 */ 549int scene_txt(struct scene *scn, const char *name, uint id, uint str_id, 550 struct scene_obj_txt **txtp); 551 552/** 553 * scene_txt_str() - add a new string to expo and text object to a scene 554 * 555 * @scn: Scene to update 556 * @name: Name to use (this is allocated by this call) 557 * @id: ID to use for the new object (0 to allocate one) 558 * @str_id: ID of the string to use 559 * @str: Pointer to text to display (allocated by caller) 560 * @txtp: If non-NULL, returns the new object 561 * Returns: ID number for the object (typically @id), or -ve on error 562 */ 563int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id, 564 const char *str, struct scene_obj_txt **txtp); 565 566/** 567 * scene_menu() - create a menu 568 * 569 * @scn: Scene to update 570 * @name: Name to use (this is allocated by this call) 571 * @id: ID to use for the new object (0 to allocate one) 572 * @menup: If non-NULL, returns the new object 573 * Returns: ID number for the object (typically @id), or -ve on error 574 */ 575int scene_menu(struct scene *scn, const char *name, uint id, 576 struct scene_obj_menu **menup); 577 578/** 579 * scene_textline() - create a textline 580 * 581 * @scn: Scene to update 582 * @name: Name to use (this is allocated by this call) 583 * @id: ID to use for the new object (0 to allocate one) 584 * @max_chars: Maximum length of the textline in characters 585 * @tlinep: If non-NULL, returns the new object 586 * Returns: ID number for the object (typically @id), or -ve on error 587 */ 588int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars, 589 struct scene_obj_textline **tlinep); 590 591/** 592 * scene_txt_set_font() - Set the font for an object 593 * 594 * @scn: Scene to update 595 * @id: ID of object to update 596 * @font_name: Font name to use (allocated by caller) 597 * @font_size: Font size to use (nominal height in pixels) 598 */ 599int scene_txt_set_font(struct scene *scn, uint id, const char *font_name, 600 uint font_size); 601 602/** 603 * scene_obj_set_pos() - Set the postion of an object 604 * 605 * @scn: Scene to update 606 * @id: ID of object to update 607 * @x: x position, in pixels from left side 608 * @y: y position, in pixels from top 609 * Returns: 0 if OK, -ENOENT if @id is invalid 610 */ 611int scene_obj_set_pos(struct scene *scn, uint id, int x, int y); 612 613/** 614 * scene_obj_set_size() - Set the size of an object 615 * 616 * @scn: Scene to update 617 * @id: ID of object to update 618 * @w: width in pixels 619 * @h: height in pixels 620 * Returns: 0 if OK, -ENOENT if @id is invalid 621 */ 622int scene_obj_set_size(struct scene *scn, uint id, int w, int h); 623 624/** 625 * scene_obj_set_hide() - Set whether an object is hidden 626 * 627 * The update happens when the expo is next rendered. 628 * 629 * @scn: Scene to update 630 * @id: ID of object to update 631 * @hide: true to hide the object, false to show it 632 * Returns: 0 if OK, -ENOENT if @id is invalid 633 */ 634int scene_obj_set_hide(struct scene *scn, uint id, bool hide); 635 636/** 637 * scene_menu_set_title() - Set the title of a menu 638 * 639 * @scn: Scene to update 640 * @id: ID of menu object to update 641 * @title_id: ID of text object to use as the title 642 * Returns: 0 if OK, -ENOENT if @id is invalid, -EINVAL if @title_id is invalid 643 */ 644int scene_menu_set_title(struct scene *scn, uint id, uint title_id); 645 646/** 647 * scene_menu_set_pointer() - Set the item pointer for a menu 648 * 649 * This is a visual indicator of the current item, typically a ">" character 650 * which sits next to the current item and moves when the user presses the 651 * up/down arrow keys 652 * 653 * @scn: Scene to update 654 * @id: ID of menu object to update 655 * @cur_item_id: ID of text or image object to use as a pointer to the current 656 * item 657 * Returns: 0 if OK, -ENOENT if @id is invalid, -EINVAL if @cur_item_id is invalid 658 */ 659int scene_menu_set_pointer(struct scene *scn, uint id, uint cur_item_id); 660 661/** 662 * scene_obj_get_hw() - Get width and height of an object in a scene 663 * 664 * @scn: Scene to check 665 * @id: ID of menu object to check 666 * @widthp: If non-NULL, returns width of object in pixels 667 * Returns: Height of object in pixels 668 */ 669int scene_obj_get_hw(struct scene *scn, uint id, int *widthp); 670 671/** 672 * scene_menuitem() - Add an item to a menu 673 * 674 * @scn: Scene to update 675 * @menu_id: ID of menu object to update 676 * @name: Name to use (this is allocated by this call) 677 * @id: ID to use for the new object (0 to allocate one) 678 * @key_id: ID of text object to use as the keypress to show 679 * @label_id: ID of text object to use as the label text 680 * @desc_id: ID of text object to use as the description text 681 * @preview_id: ID of object to use as the preview (text or image) 682 * @flags: Flags for this item (enum scene_menuitem_flags_t) 683 * @itemp: If non-NULL, returns the new object 684 * Returns: ID number for the item (typically @id), or -ve on error 685 */ 686int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, 687 uint key_id, uint label_id, uint desc_id, uint preview_id, 688 uint flags, struct scene_menitem **itemp); 689 690/** 691 * scene_arrange() - Arrange the scene to deal with object sizes 692 * 693 * Updates any menus in the scene so that their objects are in the right place. 694 * 695 * @scn: Scene to arrange 696 * Returns: 0 if OK, -ve on error 697 */ 698int scene_arrange(struct scene *scn); 699 700/** 701 * expo_send_key() - set a keypress to the expo 702 * 703 * @exp: Expo to receive the key 704 * @key: Key to send (ASCII or enum bootmenu_key) 705 * Returns: 0 if OK, -ECHILD if there is no current scene 706 */ 707int expo_send_key(struct expo *exp, int key); 708 709/** 710 * expo_action_get() - read user input from the expo 711 * 712 * @exp: Expo to check 713 * @act: Returns action 714 * Returns: 0 if OK, -EAGAIN if there was no action to return 715 */ 716int expo_action_get(struct expo *exp, struct expo_action *act); 717 718/** 719 * expo_apply_theme() - Apply a theme to an expo 720 * 721 * @exp: Expo to update 722 * @node: Node containing the theme 723 */ 724int expo_apply_theme(struct expo *exp, ofnode node); 725 726/** 727 * expo_build() - Build an expo from an FDT description 728 * 729 * Build a complete expo from a description in the provided devicetree. 730 * 731 * See doc/develop/expo.rst for a description of the format 732 * 733 * @root: Root node for expo description 734 * @expp: Returns the new expo 735 * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format 736 * error, -ENOENT if there is a references to a non-existent string 737 */ 738int expo_build(ofnode root, struct expo **expp); 739 740#endif /*__EXPO_H */ 741