Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / common / menu.c
index 94afeb290098dc4b1356496ade659d1985fcd143..5fb2ffbd065d4ed8a3dd22dddf81e8d121be5b83 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2010-2011 Calxeda, Inc.
- *
- * SPDX-License-Identifier:    GPL-2.0+
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
  */
 
 #include <common.h>
@@ -36,10 +36,12 @@ struct menu {
        int timeout;
        char *title;
        int prompt;
+       void (*display_statusline)(struct menu *);
        void (*item_data_print)(void *);
        char *(*item_choice)(void *);
        void *item_choice_data;
        struct list_head items;
+       int item_cnt;
 };
 
 /*
@@ -105,13 +107,6 @@ static inline void *menu_item_destroy(struct menu *m,
        return NULL;
 }
 
-void __menu_display_statusline(struct menu *m)
-{
-       return;
-}
-void menu_display_statusline(struct menu *m)
-       __attribute__ ((weak, alias("__menu_display_statusline")));
-
 /*
  * Display a menu so the user can make a choice of an item. First display its
  * title, if any, and then each item in the menu.
@@ -122,7 +117,8 @@ static inline void menu_display(struct menu *m)
                puts(m->title);
                putc('\n');
        }
-       menu_display_statusline(m);
+       if (m->display_statusline)
+               m->display_statusline(m);
 
        menu_items_iter(m, menu_item_print, NULL);
 }
@@ -198,13 +194,15 @@ static inline int menu_interactive_choice(struct menu *m, void **choice)
 
                if (!m->item_choice) {
                        readret = cli_readline_into_buffer("Enter choice: ",
-                                                          cbuf,
-                                                          m->timeout / 10);
+                                                          cbuf, m->timeout);
 
                        if (readret >= 0) {
                                choice_item = menu_item_by_key(m, cbuf);
                                if (!choice_item)
                                        printf("%s not found\n", cbuf);
+                       } else if (readret == -1)  {
+                               printf("<INTERRUPT>\n");
+                               return -EINTR;
                        } else {
                                return menu_default_choice(m, choice);
                        }
@@ -273,7 +271,7 @@ int menu_get_choice(struct menu *m, void **choice)
        if (!m || !choice)
                return -EINVAL;
 
-       if (!m->prompt)
+       if (!m->prompt || m->item_cnt == 1)
                return menu_default_choice(m, choice);
 
        return menu_interactive_choice(m, choice);
@@ -325,6 +323,7 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)
        item->data = item_data;
 
        list_add_tail(&item->list, &m->items);
+       m->item_cnt++;
 
        return 1;
 }
@@ -343,6 +342,9 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)
  * timeout. If 1, the user will be prompted for input regardless of the value
  * of timeout.
  *
+ * display_statusline - If not NULL, will be called to show a statusline when
+ * the menu is displayed.
+ *
  * item_data_print - If not NULL, will be called for each item when the menu
  * is displayed, with the pointer to the item's data passed as the argument.
  * If NULL, each item's key will be printed instead.  Since an item's key is
@@ -350,7 +352,7 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)
  * make it obvious what the key for each entry is.
  *
  * item_choice - If not NULL, will be called when asking the user to choose an
- * item. Returns a key string corresponding to the choosen item or NULL if
+ * item. Returns a key string corresponding to the chosen item or NULL if
  * no item has been selected.
  *
  * item_choice_data - Will be passed as the argument to the item_choice function
@@ -359,6 +361,7 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)
  * insufficient memory available to create the menu.
  */
 struct menu *menu_create(char *title, int timeout, int prompt,
+                               void (*display_statusline)(struct menu *),
                                void (*item_data_print)(void *),
                                char *(*item_choice)(void *),
                                void *item_choice_data)
@@ -373,9 +376,11 @@ struct menu *menu_create(char *title, int timeout, int prompt,
        m->default_item = NULL;
        m->prompt = prompt;
        m->timeout = timeout;
+       m->display_statusline = display_statusline;
        m->item_data_print = item_data_print;
        m->item_choice = item_choice;
        m->item_choice_data = item_choice_data;
+       m->item_cnt = 0;
 
        if (title) {
                m->title = strdup(title);