common: command: Rework the 'cmd is repeatable' logic
The repeatable property is currently attached to the main command and
sub-commands have no way to change the repeatable value (the
->repeatable field in sub-command entries is ignored).
Replace the ->repeatable field by an extended ->cmd() hook (called
->cmd_rep()) which takes a new int pointer to store the repeatable cap
of the command being executed.
With this trick, we can let sub-commands decide whether they are
repeatable or not.
We also patch mmc and dtimg who are testing the ->repeatable field
directly (they now use cmd_is_repeatable() instead), and fix the help
entry manually since it doesn't use the U_BOOT_CMD() macro.
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
diff --git a/include/command.h b/include/command.h
index 89efcec..bb93f02 100644
--- a/include/command.h
+++ b/include/command.h
@@ -29,7 +29,16 @@
struct cmd_tbl_s {
char *name; /* Command Name */
int maxargs; /* maximum number of arguments */
- int repeatable; /* autorepeat allowed? */
+ /*
+ * Same as ->cmd() except the command
+ * tells us if it can be repeated.
+ * Replaces the old ->repeatable field
+ * which was not able to make
+ * repeatable property different for
+ * the main command and sub-commands.
+ */
+ int (*cmd_rep)(struct cmd_tbl_s *cmd, int flags, int argc,
+ char * const argv[], int *repeatable);
/* Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char * const []);
char *usage; /* Usage message (short) */
@@ -60,6 +69,19 @@
extern int cmd_usage(const cmd_tbl_t *cmdtp);
+/* Dummy ->cmd and ->cmd_rep wrappers. */
+int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[], int *repeatable);
+int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[], int *repeatable);
+int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[]);
+
+static inline bool cmd_is_repeatable(cmd_tbl_t *cmdtp)
+{
+ return cmdtp->cmd_rep == cmd_always_repeatable;
+}
+
#ifdef CONFIG_AUTO_COMPLETE
extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp);
@@ -188,16 +210,28 @@
#endif
#ifdef CONFIG_CMDLINE
+#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
+ _usage, _help, _comp) \
+ { #_name, _maxargs, _cmd_rep, cmd_discard_repeatable, \
+ _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+
#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \
_usage, _help, _comp) \
- { #_name, _maxargs, _rep, _cmd, _usage, \
- _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+ { #_name, _maxargs, \
+ _rep ? cmd_always_repeatable : cmd_never_repeatable, \
+ _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
ll_entry_declare(cmd_tbl_t, _name, cmd) = \
U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \
_usage, _help, _comp);
+#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \
+ _help, _comp) \
+ ll_entry_declare(cmd_tbl_t, _name, cmd) = \
+ U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
+ _usage, _help, _comp)
+
#else
#define U_BOOT_SUBCMD_START(name) static cmd_tbl_t name[] = {};
#define U_BOOT_SUBCMD_END
@@ -209,15 +243,25 @@
_cmd(NULL, 0, 0, NULL); \
return 0; \
}
+
+#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \
+ _usage, _help, _comp) \
+ { #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage, \
+ _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
+
#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, \
_help, _comp) \
- { #_name, _maxargs, _rep, 0 ? _cmd : NULL, _usage, \
+ { #_name, _maxargs, NULL, 0 ? _cmd : NULL, _usage, \
_CMD_HELP(_help) _CMD_COMPLETE(_comp) }
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \
_comp) \
_CMD_REMOVE(sub_ ## _name, _cmd)
+#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \
+ _help, _comp) \
+ _CMD_REMOVE(sub_ ## _name, _cmd_rep)
+
#endif /* CONFIG_CMDLINE */
#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \