mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
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>
This commit is contained in:
parent
6fb61445bb
commit
80a48dd47e
5 changed files with 84 additions and 12 deletions
|
@ -116,7 +116,7 @@ static int do_dtimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
|
||||
if (!cp || argc > cp->maxargs)
|
||||
return CMD_RET_USAGE;
|
||||
if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
|
||||
if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
|
||||
return CMD_RET_SUCCESS;
|
||||
|
||||
return cp->cmd(cmdtp, flag, argc, argv);
|
||||
|
|
|
@ -29,7 +29,7 @@ U_BOOT_CMD(
|
|||
|
||||
/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */
|
||||
ll_entry_declare(cmd_tbl_t, question_mark, cmd) = {
|
||||
"?", CONFIG_SYS_MAXARGS, 1, do_help,
|
||||
"?", CONFIG_SYS_MAXARGS, cmd_always_repeatable, do_help,
|
||||
"alias for 'help'",
|
||||
#ifdef CONFIG_SYS_LONGHELP
|
||||
""
|
||||
|
|
|
@ -256,7 +256,7 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
|
|||
|
||||
if (cp == NULL || argc > cp->maxargs)
|
||||
return CMD_RET_USAGE;
|
||||
if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
|
||||
if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
|
||||
return CMD_RET_SUCCESS;
|
||||
|
||||
mmc = init_mmc_device(curr_device, false);
|
||||
|
@ -916,7 +916,7 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
|
||||
if (cp == NULL || argc > cp->maxargs)
|
||||
return CMD_RET_USAGE;
|
||||
if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
|
||||
if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
|
||||
return CMD_RET_SUCCESS;
|
||||
|
||||
if (curr_device < 0) {
|
||||
|
|
|
@ -501,6 +501,30 @@ void fixup_cmdtable(cmd_tbl_t *cmdtp, int size)
|
|||
}
|
||||
#endif
|
||||
|
||||
int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[], int *repeatable)
|
||||
{
|
||||
*repeatable = 1;
|
||||
|
||||
return cmdtp->cmd(cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[], int *repeatable)
|
||||
{
|
||||
*repeatable = 0;
|
||||
|
||||
return cmdtp->cmd(cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
int repeatable;
|
||||
|
||||
return cmdtp->cmd_rep(cmdtp, flag, argc, argv, &repeatable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a command function. This should be the only route in U-Boot to call
|
||||
* a command, so that we can track whether we are waiting for input or
|
||||
|
@ -510,13 +534,15 @@ void fixup_cmdtable(cmd_tbl_t *cmdtp, int size)
|
|||
* @param flag Some flags normally 0 (see CMD_FLAG_.. above)
|
||||
* @param argc Number of arguments (arg 0 must be the command text)
|
||||
* @param argv Arguments
|
||||
* @param repeatable Can the command be repeated
|
||||
* @return 0 if command succeeded, else non-zero (CMD_RET_...)
|
||||
*/
|
||||
static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
|
||||
int *repeatable)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
|
||||
result = cmdtp->cmd_rep(cmdtp, flag, argc, argv, repeatable);
|
||||
if (result)
|
||||
debug("Command failed, result=%d\n", result);
|
||||
return result;
|
||||
|
@ -553,12 +579,14 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
|
|||
|
||||
/* If OK so far, then do the command */
|
||||
if (!rc) {
|
||||
int newrep;
|
||||
|
||||
if (ticks)
|
||||
*ticks = get_timer(0);
|
||||
rc = cmd_call(cmdtp, flag, argc, argv);
|
||||
rc = cmd_call(cmdtp, flag, argc, argv, &newrep);
|
||||
if (ticks)
|
||||
*ticks = get_timer(*ticks);
|
||||
*repeatable &= cmdtp->repeatable;
|
||||
*repeatable &= newrep;
|
||||
}
|
||||
if (rc == CMD_RET_USAGE)
|
||||
rc = cmd_usage(cmdtp);
|
||||
|
|
|
@ -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 @@ int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc,
|
|||
|
||||
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 @@ int board_run_command(const char *cmdline);
|
|||
#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 @@ int board_run_command(const char *cmdline);
|
|||
_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) \
|
||||
|
|
Loading…
Reference in a new issue