@@ -39,7 +39,7 @@ discover_objs = discover/udev.o discover
discover/device-handler.o discover/paths.o
# client objs
-ui_common_objs = ui/common/discover-client.o
+ui_common_objs = ui/common/discover-client.o ui/common/menu.o
ncurses_objs =
twin_objs = ui/twin/pb-twin.o
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2009 Sony Computer Entertainment Inc.
+ * Copyright 2009 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+
+#include "log/log.h"
+#include "talloc/talloc.h"
+#include "ui/common/menu.h"
+
+/**
+ * menu_item_init - Allocate and initialize a new menu_item instance.
+ *
+ * Returns a pointer the the initialized struct menu_item instance or NULL
+ * on error. The caller is responsible for calling talloc_free() for the
+ * returned instance.
+ */
+
+struct menu_item *menu_item_init(struct menu *menu, enum menu_item_type type,
+ enum menu_item_state state, const char* text)
+{
+ struct menu_item *i = talloc_zero(menu, struct menu_item);
+
+ if (i) {
+ i->i_sig = menu_item_sig;
+ i->type = type;
+ i->state = state;
+ i->text = text ? text : "";
+ i->status = "";
+ }
+
+ return i;
+}
+
+/**
+ * menu_item_delete - Delete a menu_item instance.
+ *
+ */
+
+void menu_item_delete(struct menu_item *i)
+{
+ assert(i->i_sig == menu_item_sig);
+ i->i_sig = menu_removed_sig;
+ talloc_free(i);
+}
+
+/**
+ * menu_item_set_text - Set menu_item text.
+ * @text: Reference taken, must be persistant.
+ */
+
+void menu_item_set_text(struct menu_item *i, const char *text)
+{
+ i->text = text ? text : "";
+}
+
+/**
+ * menu_init - Allocate and initialize a new menu instance.
+ *
+ * Returns a pointer the the initialized struct menu instance or NULL on error.
+ * The caller is responsible for calling talloc_free() for the returned
+ * instance.
+ */
+
+struct menu *menu_init(void* ctx)
+{
+ struct menu *menu = talloc_zero(ctx, struct menu);
+
+ if (menu) {
+ menu->m_sig = menu_sig;
+ list_init(&menu->items);
+ }
+
+ return menu;
+}
+
+/**
+ * menu_delete - Delete a menu instance.
+ *
+ */
+
+void menu_delete(struct menu *menu)
+{
+ assert(menu->m_sig == menu_sig);
+ menu->m_sig = menu_removed_sig;
+ talloc_free(menu);
+}
+
+/**
+ * menu_draw - Display the menu.
+ * @menu: A menu instance returned from menu_init().
+ */
+
+void menu_draw(const struct menu *menu)
+{
+ struct menu_item *i;
+ int y;
+
+ assert(menu->m_sig == menu_sig);
+ assert(menu->draw_item);
+
+ if (menu->draw_start)
+ menu->draw_start(menu);
+ y = 0;
+
+ list_for_each_entry(&menu->items, i, list)
+ if (i->state == state_visable || i->state == state_selected) {
+ assert(i->text);
+ menu->draw_item(menu, i, y++);
+ }
+
+ if (menu->draw_end)
+ menu->draw_end(menu);
+}
+
+static void menu_set_status(struct menu *menu, const char *text)
+{
+ if (menu->status)
+ menu_item_set_text(menu->status, text);
+}
+
+/**
+ * menu_key_up -
+ * @menu: A menu instance returned from menu_init().
+ *
+ * Calls menu_draw().
+ */
+
+void menu_key_up(struct menu *menu)
+{
+ struct menu_item *i;
+ struct menu_item *current = NULL;
+ struct menu_item *next = NULL;
+
+ assert(menu->m_sig == menu_sig);
+
+ list_for_each_entry(&menu->items, i, list) {
+ if (i->state == state_selected) {
+ current = i;
+ break;
+ }
+ if (i->type != type_text && i->state == state_visable)
+ next = i;
+ }
+
+ assert(current);
+
+ if (next) {
+ current->state = state_visable;
+ next->state = state_selected;
+ menu_set_status(menu, next->status);
+ menu_draw(menu);
+ }
+}
+
+/**
+ * menu_key_down -
+ * @menu: A menu instance returned from menu_init().
+ */
+
+void menu_key_down(struct menu *menu)
+{
+ struct menu_item *i;
+ struct menu_item *current = NULL;
+ struct menu_item *next = NULL;
+
+ assert(menu->m_sig == menu_sig);
+
+ list_for_each_entry(&menu->items, i, list)
+ if (i->state == state_selected) {
+ current = i;
+ break;
+ }
+
+ assert(current);
+
+ list_continue_each_entry(&menu->items, i, list)
+ if (i->type != type_text && i->state == state_visable) {
+ next = i;
+ break;
+ }
+
+ if (next) {
+ current->state = state_visable;
+ next->state = state_selected;
+ menu_set_status(menu, next->status);
+ menu_draw(menu);
+ }
+}
+
+/**
+ * menu_set_item_text - Set menu_item text and redraw menu.
+ */
+
+void menu_set_item_text(struct menu *menu, struct menu_item *i,
+ const char *text)
+{
+ menu_item_set_text(i, text);
+ menu_draw(menu);
+}
+
+/**
+ * menu_item_kexec - Run kexec with the supplied boot options.
+ * @opt: Pointer to a @struct boot_option data structure.
+ */
+
+static int menu_item_kexec(const struct menu_item_kexec *kexec)
+{
+ pb_log("%s: %s\n", __func__, kexec->opt->name);
+ return 0;
+}
+
+/**
+ * menu_item_exec - Run exec with the supplied command.
+ * @cmd: A command string.
+ */
+
+static int menu_item_exec(const char* cmd)
+{
+ pb_log("%s: %s\n", __func__, cmd);
+ return 0;
+}
+
+/**
+ * menu_item_process - Execute the action associated with the item.
+ * @i: The item to execute.
+ */
+
+static int menu_item_process(const struct menu_item *i)
+{
+ assert(i->i_sig == menu_item_sig);
+
+ switch (i->type) {
+ case type_kexec:
+ pb_log("%s: kexec: %s\n", __func__, i->text);
+ return menu_item_kexec(&i->kexec);
+ case type_callback:
+ pb_log("%s: callback: %s\n", __func__, i->text);
+ return i->cb->fn(i->cb->arg);
+ case type_cmd:
+ pb_log("%s: cmd: %s\n", __func__, i->text);
+ return menu_item_exec(i->cmd);
+ case type_text:
+ default:
+ assert(0 && "bad type");
+ break;
+ }
+ return -1;
+}
+
+/**
+ * menu_key_execute -
+ * @menu: A menu instance returned from menu_init().
+ */
+
+int menu_key_execute(struct menu *menu)
+{
+ struct menu_item *i;
+
+ assert(menu->m_sig == menu_sig);
+
+ list_for_each_entry(&menu->items, i, list)
+ if (i->state == state_selected)
+ return menu_item_process(i);
+
+ assert(0 && "no state_selected");
+ return -1;
+}
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009 Sony Computer Entertainment Inc.
+ * Copyright 2009 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if !defined(_PB_MENU_H)
+#define _PB_MENU_H
+
+#include "list/list.h"
+#include "pb-protocol/pb-protocol.h"
+
+#if defined(__cplusplus)
+# define EXTERN_C extern "C"
+#else
+# define EXTERN_C
+#endif
+
+enum menu_sig {
+ menu_sig = 333,
+ menu_item_sig = 444,
+ menu_removed_sig = -555,
+};
+
+/**
+ * enum menu_item_type - The type or action of the menu item.
+ * @type_text: A simple text item with no action, cannot be selected.
+ * @type_kexec: A selectable item that runs kexec.
+ * @type_callback: A selectable item that has an associated callback routine.
+ * @type_cmd: A selectable item that runs a command via exec().
+ */
+
+enum menu_item_type {
+ type_text = 0,
+ type_callback,
+ type_cmd,
+ type_kexec,
+};
+
+/**
+ * struct menu_item_callback - Data structure for @type_callback items.
+ * @fn: The user supplied callback routine.
+ * @arg: A user supplied argument passed to the callback routine.
+ */
+
+struct menu_item_callback {
+ int (*fn)(void *arg);
+ void* arg;
+};
+
+/**
+ * struct menu_item_kexec - Data structure for @type_kexec items.
+ * @dev: A pointer to the device.
+ * @opt: A pointer to the boot option.
+ */
+
+struct menu_item_kexec {
+ const struct device *dev;
+ const struct boot_option *opt;
+};
+
+/**
+ * enum menu_item_state
+ * @state_visable: The default state, visable.
+ * @state_hidden: Used to hide items to declutter the display.
+ * @state_selected: Only a single item can be selected at a time.
+ */
+
+enum menu_item_state {
+ state_visable = 0,
+ state_hidden,
+ state_selected,
+};
+
+/**
+ * struct menu_item - Data structure defining a single menu item.
+ * @i_sig: Signature for callback type checking, should be menu_item_sig.
+ * @text: The text displayed for the menu item.
+ */
+
+struct menu_item {
+ enum menu_sig i_sig;
+ struct list_item list;
+ enum menu_item_type type;
+ enum menu_item_state state;
+ const char* text;
+ const char* status;
+ union {
+ struct menu_item_kexec kexec;
+ const char* cmd;
+ const struct menu_item_callback* cb;
+ };
+};
+
+/**
+ * struct menu - Data structure defining complete menu.
+ * @m_sig: Signature for callback type checking, should be menu_sig.
+ * @items: The list of menu_items to be displayed as the menu.
+ * @status: Pointer to a menu_item (in @items) to be used as the menu's status
+ * line. Set with menu_set_status_item().
+ * @insert_start: Optional pointer to a menu_item (in @items) that defines a
+ * starting point for adding dynamic items.
+ * @insert_end: Optional pointer to a menu_item (in @items) that defines a
+ * end point for adding dynamic items.
+ * @ui_info: FIXME need this???
+ * @draw_start: Optional user supplied callback to prepare for drawing.
+ * @draw_item: User callback to draw an item, called once for each item in the
+ * menu.
+ * @draw_end: Optional user supplied callback to finalise drawing.
+ */
+
+struct menu {
+ enum menu_sig m_sig;
+ struct list items;
+ struct menu_item *status;
+ struct menu_item *insert_start;
+ struct menu_item *insert_end;
+ //void *ui_info;
+ void (*draw_start)(const struct menu *menu);
+ void (*draw_item)(const struct menu *menu, const struct menu_item *i,
+ int y);
+ void (*draw_end)(const struct menu *menu);
+};
+
+#define to_menu_item(_arg) \
+ (assert(((struct menu_item *)(_arg))->i_sig == menu_item_sig), \
+ ((struct menu_item *)(_arg)))
+
+EXTERN_C struct menu_item *menu_item_init(struct menu *menu,
+ enum menu_item_type type, enum menu_item_state state, const char* text);
+EXTERN_C void menu_item_delete(struct menu_item *i);
+EXTERN_C void menu_item_set_text(struct menu_item *i, const char *text);
+
+#define to_menu(_arg) \
+ (assert(((struct menu *)(_arg))->m_sig == menu_sig), \
+ ((struct menu *)(_arg)))
+
+EXTERN_C struct menu *menu_init(void* ctx);
+EXTERN_C void menu_delete(struct menu *menu);
+EXTERN_C void menu_draw(const struct menu *menu);
+EXTERN_C void menu_key_up(struct menu *menu);
+EXTERN_C void menu_key_down(struct menu *menu);
+EXTERN_C int menu_key_execute(struct menu *menu);
+EXTERN_C void menu_set_item_text(struct menu *menu, struct menu_item *i,
+ const char *text); // FIXME need this???
+
+static inline void menu_set_status_item(struct menu *menu, struct menu_item *i)
+{
+ menu->status = i;
+}
+
+#endif
Add support for a generic UI menu system. Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> --- rules.mk | 2 ui/common/menu.c | 284 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui/common/menu.h | 164 +++++++++++++++++++++++++++++++ 3 files changed, 449 insertions(+), 1 deletion(-)