You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
9.4 KiB
363 lines
9.4 KiB
3 years ago
|
/**
|
||
|
* Console - VCOM command engine
|
||
|
*
|
||
|
* Created on 2020/02/28 by Ondrej Hruska
|
||
|
*
|
||
|
* Parts are based on the console component from esp-idf
|
||
|
* licensed under the Apache 2 license.
|
||
|
*/
|
||
|
|
||
|
#ifndef LIBCONSOLE_H
|
||
|
#define LIBCONSOLE_H
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <console/config.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
typedef enum {
|
||
|
/* Colors */
|
||
|
COLOR_RESET = 0xF0,
|
||
|
COLOR_BLACK = 0x01,
|
||
|
COLOR_RED = 0x02,
|
||
|
COLOR_GREEN = 0x03,
|
||
|
COLOR_YELLOW = 0x04,
|
||
|
COLOR_BLUE = 0x05,
|
||
|
COLOR_MAGENTA = 0x06,
|
||
|
COLOR_CYAN = 0x07,
|
||
|
COLOR_WHITE = 0x08,
|
||
|
/* Modifiers */
|
||
|
COLOR_NORMAL = 0x0F,
|
||
|
COLOR_BOLD = 0x10,
|
||
|
COLOR_UNDERLINE = 0x20,
|
||
|
COLOR_BLINK = 0x30,
|
||
|
COLOR_HIDE = 0x40,
|
||
|
} console_color_t;
|
||
|
|
||
|
#if CONSOLE_USE_FREERTOS
|
||
|
#include "freertos/FreeRTOS.h"
|
||
|
#include "freertos/task.h"
|
||
|
#include "freertos/semphr.h"
|
||
|
|
||
|
typedef SemaphoreHandle_t console_mutex_t;
|
||
|
#endif
|
||
|
|
||
|
#if CONSOLE_USE_PTHREADS
|
||
|
#include <pthread.h>
|
||
|
typedef pthread_mutex_t console_mutex_t;
|
||
|
#endif
|
||
|
|
||
|
#if CONSOLE_USE_TERMIOS
|
||
|
#include <termios.h>
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* Console config struct
|
||
|
*/
|
||
|
struct console_config {
|
||
|
/**
|
||
|
* Timeout waiting for execution lock when handling a command.
|
||
|
* This should be longer than the slowest command in the system.
|
||
|
*/
|
||
|
uint32_t execution_lock_timeout_ms;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Macro to init the console config struct
|
||
|
*/
|
||
|
#define CONSOLE_CONFIG_DEFAULTS() { \
|
||
|
.execution_lock_timeout_ms = 10000, \
|
||
|
}
|
||
|
|
||
|
typedef struct console_config console_config_t;
|
||
|
|
||
|
struct console_ctx; // early declaration
|
||
|
|
||
|
/**
|
||
|
* Console context
|
||
|
*/
|
||
|
typedef struct console_ctx console_ctx_t;
|
||
|
|
||
|
/**
|
||
|
* Console errors - return codes
|
||
|
*/
|
||
|
enum console_err {
|
||
|
CONSOLE_OK = 0,
|
||
|
/** unspecified error */
|
||
|
CONSOLE_ERROR = 1,
|
||
|
/** Allocation failed */
|
||
|
CONSOLE_ERR_NO_MEM,
|
||
|
/** Function call not allowed (e.g. console not inited) */
|
||
|
CONSOLE_ERR_BAD_CALL,
|
||
|
/** Argument validation failed */
|
||
|
CONSOLE_ERR_INVALID_ARG,
|
||
|
/** Command not recognized */
|
||
|
CONSOLE_ERR_UNKNOWN_CMD,
|
||
|
/** Timeout */
|
||
|
CONSOLE_ERR_TIMEOUT,
|
||
|
/** IO error (file open fail, etc.) */
|
||
|
CONSOLE_ERR_IO,
|
||
|
/** Operation denied (not allowed / insufficient rights) */
|
||
|
CONSOLE_ERR_NOT_POSSIBLE,
|
||
|
/** End marker */
|
||
|
_CONSOLE_ERR_MAX,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Print string describing console error.
|
||
|
* In case of unknown error, the number is shown.
|
||
|
*
|
||
|
* The argument should be `enum console_err`, but any number is valid.
|
||
|
*/
|
||
|
void console_err_print_ctx(struct console_ctx *ctx, int e);
|
||
|
|
||
|
// TODO error-to-string function
|
||
|
|
||
|
typedef enum console_err console_err_t;
|
||
|
|
||
|
// early decl's
|
||
|
struct cmd_signature;
|
||
|
typedef struct cmd_signature cmd_signature_t;
|
||
|
|
||
|
/**
|
||
|
* Command signature, passed as the last argument to the command handler
|
||
|
* to perform registration.
|
||
|
*
|
||
|
* \note Fill only fields that differ from default (zeros/NULLs)
|
||
|
*/
|
||
|
struct cmd_signature {
|
||
|
const char* command; //!< Command name, used in invocations (filled internally, do not set)
|
||
|
const char* help; //!< Command help text, shown when called with -h
|
||
|
const char* hint; //!< Hint text, generated from argtable if hint==NULL & argtable!=NULL
|
||
|
bool no_history; //!< Command skips history
|
||
|
bool custom_args; //!< Disable argtable parsing in the handler function, will be parsed manually from argv/argc
|
||
|
|
||
|
/**
|
||
|
* Argtable, struct or array that must end with arg_end().
|
||
|
* Used by the register function and for disambiguation.
|
||
|
*/
|
||
|
void* argtable;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Active console context pointer, valid only when handling a console command (otherwise NULL).
|
||
|
*
|
||
|
* Used by the console printf & other IO methods.
|
||
|
*/
|
||
|
extern struct console_ctx * console_active_ctx;
|
||
|
|
||
|
/**
|
||
|
* Function handling a callback from the console loop.
|
||
|
*/
|
||
|
typedef void(*console_callback_t)(console_ctx_t *ctx);
|
||
|
|
||
|
/**
|
||
|
* Console context struct
|
||
|
*/
|
||
|
struct console_ctx {
|
||
|
#if CONSOLE_USE_FILE_IO_STREAMS
|
||
|
// Streams
|
||
|
FILE* in; //!< stdin fd, can be -1 if not available (running commands in non-interactive mode)
|
||
|
FILE* out; //!< stdout fd
|
||
|
|
||
|
#if CONSOLE_USE_TERMIOS
|
||
|
// original termios is stored here before entering raw mode
|
||
|
struct termios orig_termios;
|
||
|
#endif
|
||
|
|
||
|
#else
|
||
|
void *ioctx;
|
||
|
#endif //CONSOLE_USE_FILE_IO_STREAMS
|
||
|
|
||
|
#if CONSOLE_FILE_SUPPORT
|
||
|
char *history_file;
|
||
|
#endif //CONSOLE_FILE_SUPPORT
|
||
|
|
||
|
bool __internal_heap_allocated;
|
||
|
bool exit_allowed;
|
||
|
|
||
|
char prompt[CONSOLE_PROMPT_MAX_LEN]; //!< Prompt, can be modified by a command or `before_readline_fn`
|
||
|
char line_buffer[CONSOLE_LINE_BUF_LEN];
|
||
|
|
||
|
/**
|
||
|
* Callback fired in the command evaluation loop, each time before the prompt is shown and new line read.
|
||
|
* This command can print to the output streams, change prompt, shutdown console, etc.
|
||
|
*/
|
||
|
console_callback_t loop_handler;
|
||
|
|
||
|
/**
|
||
|
* Callback fired before the console task shuts down
|
||
|
*/
|
||
|
console_callback_t shutdown_handler;
|
||
|
|
||
|
/**
|
||
|
* Shutdown requested. Console will exit as soon as possible.
|
||
|
*/
|
||
|
bool exit_requested;
|
||
|
|
||
|
/**
|
||
|
* Interactive mode. Enables additional outputs for user convenience.
|
||
|
*/
|
||
|
bool interactive;
|
||
|
|
||
|
/**
|
||
|
* Enable ANSI colors
|
||
|
*/
|
||
|
bool use_colors;
|
||
|
|
||
|
/* These fields are valid only during command execution */
|
||
|
const char **argv; //!< The current argv
|
||
|
size_t argc; //!< The current argc
|
||
|
const cmd_signature_t *cmd; //!< Pointer to the currently executed command signature
|
||
|
|
||
|
/** Used for argument validation */
|
||
|
uint32_t __internal_magic;
|
||
|
};
|
||
|
|
||
|
#define CONSOLE_CTX_MAGIC 0x6f587468
|
||
|
|
||
|
/**
|
||
|
* Command handler type.
|
||
|
*
|
||
|
* @param ctx - console context, including input/output files
|
||
|
* @param reg - signature struct; if not NULL, init the static argtable, fill this struct, and return OK (0).
|
||
|
* @return status code, 0 = OK (use cons_err_t constants if possible)
|
||
|
*/
|
||
|
typedef int (*console_command_t)(console_ctx_t *ctx, struct cmd_signature *reg);
|
||
|
|
||
|
/**
|
||
|
* Intialize the console
|
||
|
*
|
||
|
* @param config - config pointer, NULL to use defaults
|
||
|
* @return status code
|
||
|
*/
|
||
|
console_err_t console_init(const console_config_t *config);
|
||
|
|
||
|
/**
|
||
|
* @brief Register console command
|
||
|
*
|
||
|
* If the command function is already registered, this creates an alias.
|
||
|
* A multi-word command automatically create a command group. The group can
|
||
|
* be described using a description string by calling `console_group_add()`
|
||
|
* - at convenience before or after the commands are registered.
|
||
|
*
|
||
|
* @param name - command name (may contain spaces for "multi-part commands")
|
||
|
* @param handler pointer to the command handler.
|
||
|
* @return status code
|
||
|
*/
|
||
|
console_err_t console_cmd_register(console_command_t handler, const char *name);
|
||
|
|
||
|
/**
|
||
|
* @brief Register a command group.
|
||
|
*
|
||
|
* Command groups are created automatically when used.
|
||
|
* This method can create a group with description, or attach a custom description
|
||
|
* to an existing group.
|
||
|
*
|
||
|
* @param name - group name (first word of multi-part commands)
|
||
|
* @param descr - description to attach, can be NULL
|
||
|
* @return staus code
|
||
|
*/
|
||
|
console_err_t console_group_add(const char *name, const char *descr);
|
||
|
|
||
|
/**
|
||
|
* Add alias to an existing command by name.
|
||
|
*
|
||
|
* @param original - original command name
|
||
|
* @param alias - command's alias
|
||
|
* @return status code
|
||
|
*/
|
||
|
console_err_t console_cmd_add_alias(const char *original, const char *alias);
|
||
|
|
||
|
/**
|
||
|
* Add alias by handler function
|
||
|
*
|
||
|
* @param handler - command handler
|
||
|
* @param alias - new name
|
||
|
* @return status code
|
||
|
*/
|
||
|
console_err_t console_cmd_add_alias_fn(console_command_t handler, const char *alias);
|
||
|
|
||
|
/**
|
||
|
* Internal error print function. Has WEAK linkage, can be overridden.
|
||
|
*
|
||
|
* This function is used to report detected bugs and should not be called
|
||
|
* in well-written "production code".
|
||
|
*
|
||
|
* @param msg - error message
|
||
|
*/
|
||
|
void console_internal_error_print(const char *msg);
|
||
|
|
||
|
/**
|
||
|
* This function is guarded by a mutex and will wait for the execution lock as
|
||
|
* configured in console_config.
|
||
|
*
|
||
|
* @brief Run command line
|
||
|
* @param[in] outf
|
||
|
* @param[in] inf
|
||
|
* @param cmdline command line (command name followed by a number of arguments)
|
||
|
* @param[out] pRetval return code from the command (set if command was run)
|
||
|
* @param[out] pCommandSig - is set to a pointer to the matched command signature, or NULL on error
|
||
|
* @return status code
|
||
|
*/
|
||
|
console_err_t console_handle_cmd(
|
||
|
console_ctx_t *ctx,
|
||
|
const char *cmdline,
|
||
|
int *pRetval,
|
||
|
const struct cmd_signature **pCommandSig
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Count all registered commands
|
||
|
*
|
||
|
* @return
|
||
|
*/
|
||
|
size_t console_count_commands(void);
|
||
|
|
||
|
/**
|
||
|
* Create a console IO context and init it to defaults.
|
||
|
*
|
||
|
* takes stdin and stdout file descriptors, or IO context (based on config flags)
|
||
|
*
|
||
|
* In the FD variant, pass NULL as STDIN if not available.
|
||
|
*
|
||
|
* @param ctx - context, if using static alloc, NULL to allocate internally.
|
||
|
* @return the context, NULL if alloc or init fails
|
||
|
*/
|
||
|
console_ctx_t *console_ctx_init(
|
||
|
console_ctx_t *ctx,
|
||
|
#if CONSOLE_USE_FILE_IO_STREAMS
|
||
|
FILE* inf, FILE* outf
|
||
|
#else
|
||
|
void * ioctx
|
||
|
#endif
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Destroy a console IO context.
|
||
|
*
|
||
|
* Make sure to release any user fields (ioctx, for example) beforehand.
|
||
|
*
|
||
|
* @attention ONLY CALL THIS IF THE CONTEXT WAS DYNAMICALLY ALLOCATED!
|
||
|
*
|
||
|
* @param[in,out] ctx - pointer to context, will be set to NULL.
|
||
|
*/
|
||
|
void console_ctx_destroy(console_ctx_t *ctx);
|
||
|
|
||
|
/**
|
||
|
* Console task
|
||
|
*
|
||
|
* @param[in] param - must be a valid console context (see `console_ctx_init()`)
|
||
|
*/
|
||
|
void console_task(void *param);
|
||
|
|
||
|
/**
|
||
|
* Variant of 'console_task' for pthreads (returns NULL)
|
||
|
*/
|
||
|
void* console_task_posix(void *param);
|
||
|
|
||
|
#include "console_io.h"
|
||
|
|
||
|
#endif //LIBCONSOLE_H
|