mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-04-28 19:54:01 +00:00
hv: shell: improve console to modify input easier
1. make memcpy_erms as a public API; add a new one memcpy_erms_backwards, which supports to copy data from tail to head. 2. improve to use right/left/home/end key to move cursor, and support delete/backspace key to modify current input command. Tracked-On: #7931 Signed-off-by: Minggui Cao <minggui.cao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
d5b2c82156
commit
83164d6030
@ -24,7 +24,7 @@ void *memset(void *base, uint8_t v, size_t n)
|
||||
return base;
|
||||
}
|
||||
|
||||
static inline void memcpy_erms(void *d, const void *s, size_t slen)
|
||||
void memcpy_erms(void *d, const void *s, size_t slen)
|
||||
{
|
||||
asm volatile ("rep; movsb"
|
||||
: "=&D"(d), "=&S"(s)
|
||||
@ -32,6 +32,15 @@ static inline void memcpy_erms(void *d, const void *s, size_t slen)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/* copy data from tail to head (backwards) with ERMS (Enhanced REP MOVSB/STOSB) */
|
||||
void memcpy_erms_backwards(void *d, const void *s, size_t slen)
|
||||
{
|
||||
asm volatile ("std; rep; movsb; cld"
|
||||
: "=&D"(d), "=&S"(s)
|
||||
: "c"(slen), "0" (d), "1" (s)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Copies at most slen bytes from src address to dest address, up to dmax.
|
||||
*
|
||||
|
@ -157,12 +157,17 @@ static struct shell_cmd shell_cmds[] = {
|
||||
},
|
||||
};
|
||||
|
||||
/* for function key: up/down key */
|
||||
/* for function key: up/down/right/left/home/end and delete key */
|
||||
enum function_key {
|
||||
KEY_NONE,
|
||||
|
||||
KEY_DELETE = 0x5B33,
|
||||
KEY_UP = 0x5B41,
|
||||
KEY_DOWN = 0x5B42,
|
||||
KEY_RIGHT = 0x5B43,
|
||||
KEY_LEFT = 0x5B44,
|
||||
KEY_END = 0x5B46,
|
||||
KEY_HOME = 0x5B48,
|
||||
};
|
||||
|
||||
/* The initial log level*/
|
||||
@ -287,6 +292,40 @@ static void clear_input_line(uint32_t len)
|
||||
}
|
||||
}
|
||||
|
||||
static void set_cursor_pos(uint32_t left_offset)
|
||||
{
|
||||
while (left_offset > 0) {
|
||||
left_offset--;
|
||||
shell_puts("\b");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_delete_key(void)
|
||||
{
|
||||
if (p_shell->cursor_offset < p_shell->input_line_len) {
|
||||
|
||||
uint32_t delta = p_shell->input_line_len - p_shell->cursor_offset - 1;
|
||||
|
||||
/* Send a space + backspace sequence to delete character */
|
||||
shell_puts(" \b");
|
||||
|
||||
/* display the left input chars and remove former last one */
|
||||
shell_puts(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset + 1);
|
||||
shell_puts(" \b");
|
||||
|
||||
set_cursor_pos(delta);
|
||||
|
||||
memcpy_erms(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset,
|
||||
p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset + 1, delta);
|
||||
|
||||
/* Null terminate the last character to erase it */
|
||||
p_shell->buffered_line[p_shell->input_line_active][p_shell->input_line_len - 1] = 0;
|
||||
|
||||
/* Reduce the length of the string by one */
|
||||
p_shell->input_line_len--;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_updown_key(enum function_key key_value)
|
||||
{
|
||||
int32_t to_select, current_select = p_shell->to_select_index;
|
||||
@ -316,6 +355,10 @@ static void handle_updown_key(enum function_key key_value)
|
||||
}
|
||||
|
||||
if (strcmp(p_shell->buffered_line[current_select], p_shell->buffered_line[p_shell->input_line_active]) != 0) {
|
||||
/* reset cursor pos and clear current input line first, then output selected cmd */
|
||||
if (p_shell->cursor_offset < p_shell->input_line_len) {
|
||||
shell_puts(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset);
|
||||
}
|
||||
|
||||
clear_input_line(p_shell->input_line_len);
|
||||
shell_puts(p_shell->buffered_line[current_select]);
|
||||
@ -325,6 +368,7 @@ static void handle_updown_key(enum function_key key_value)
|
||||
memcpy_s(p_shell->buffered_line[p_shell->input_line_active], SHELL_CMD_MAX_LEN,
|
||||
p_shell->buffered_line[current_select], len + 1);
|
||||
p_shell->input_line_len = len;
|
||||
p_shell->cursor_offset = len;
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,15 +377,46 @@ static void shell_handle_special_char(char ch)
|
||||
enum function_key key_value = KEY_NONE;
|
||||
|
||||
switch (ch) {
|
||||
/* original function key value: ESC + key, so consume the next 2 characters */
|
||||
/* original function key value: ESC + key (2/3 bytes), so consume the next 2/3 characters */
|
||||
case 0x1b:
|
||||
key_value = (shell_getc() << 8) | shell_getc();
|
||||
if (key_value == KEY_DELETE) {
|
||||
(void)shell_getc(); /* delete key has one more byte */
|
||||
}
|
||||
|
||||
switch (key_value) {
|
||||
case KEY_DELETE:
|
||||
handle_delete_key();
|
||||
break;
|
||||
case KEY_UP:
|
||||
case KEY_DOWN:
|
||||
handle_updown_key(key_value);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
if (p_shell->cursor_offset < p_shell->input_line_len) {
|
||||
shell_puts(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset);
|
||||
p_shell->cursor_offset++;
|
||||
set_cursor_pos(p_shell->input_line_len - p_shell->cursor_offset);
|
||||
}
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
if (p_shell->cursor_offset > 0) {
|
||||
p_shell->cursor_offset--;
|
||||
shell_puts("\b");
|
||||
}
|
||||
break;
|
||||
case KEY_END:
|
||||
if (p_shell->cursor_offset < p_shell->input_line_len) {
|
||||
shell_puts(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset);
|
||||
p_shell->cursor_offset = p_shell->input_line_len;
|
||||
}
|
||||
break;
|
||||
case KEY_HOME:
|
||||
if (p_shell->cursor_offset > 0) {
|
||||
set_cursor_pos(p_shell->cursor_offset);
|
||||
p_shell->cursor_offset = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -358,6 +433,57 @@ static void shell_handle_special_char(char ch)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_backspace_key(void)
|
||||
{
|
||||
/* Ensure length is not 0 */
|
||||
if (p_shell->cursor_offset > 0U) {
|
||||
/* Echo backspace */
|
||||
shell_puts("\b");
|
||||
/* Send a space + backspace sequence to delete character */
|
||||
shell_puts(" \b");
|
||||
|
||||
if (p_shell->cursor_offset < p_shell->input_line_len) {
|
||||
uint32_t delta = p_shell->input_line_len - p_shell->cursor_offset;
|
||||
|
||||
/* display the left input-chars and remove the former last one */
|
||||
shell_puts(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset);
|
||||
shell_puts(" \b");
|
||||
|
||||
set_cursor_pos(delta);
|
||||
memcpy_erms(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset - 1,
|
||||
p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset, delta);
|
||||
}
|
||||
|
||||
/* Null terminate the last character to erase it */
|
||||
p_shell->buffered_line[p_shell->input_line_active][p_shell->input_line_len - 1] = 0;
|
||||
|
||||
/* Reduce the length of the string by one */
|
||||
p_shell->input_line_len--;
|
||||
p_shell->cursor_offset--;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_input_char(char ch)
|
||||
{
|
||||
uint32_t delta = p_shell->input_line_len - p_shell->cursor_offset;
|
||||
|
||||
/* move the input from cursor offset back first */
|
||||
if (delta > 0) {
|
||||
memcpy_erms_backwards(p_shell->buffered_line[p_shell->input_line_active] + p_shell->input_line_len,
|
||||
p_shell->buffered_line[p_shell->input_line_active] + p_shell->input_line_len - 1, delta);
|
||||
}
|
||||
|
||||
p_shell->buffered_line[p_shell->input_line_active][p_shell->cursor_offset] = ch;
|
||||
|
||||
/* Echo back the input */
|
||||
shell_puts(p_shell->buffered_line[p_shell->input_line_active] + p_shell->cursor_offset);
|
||||
set_cursor_pos(delta);
|
||||
|
||||
/* Move to next character in string */
|
||||
p_shell->input_line_len++;
|
||||
p_shell->cursor_offset++;
|
||||
}
|
||||
|
||||
static bool shell_input_line(void)
|
||||
{
|
||||
bool done = false;
|
||||
@ -369,22 +495,7 @@ static bool shell_input_line(void)
|
||||
switch (ch) {
|
||||
/* Backspace */
|
||||
case '\b':
|
||||
/* Ensure length is not 0 */
|
||||
if (p_shell->input_line_len > 0U) {
|
||||
/* Reduce the length of the string by one */
|
||||
p_shell->input_line_len--;
|
||||
|
||||
/* Null terminate the last character to erase it */
|
||||
p_shell->buffered_line[p_shell->input_line_active][p_shell->input_line_len] = 0;
|
||||
|
||||
/* Echo backspace */
|
||||
shell_puts("\b");
|
||||
|
||||
/* Send a space + backspace sequence to delete
|
||||
* character
|
||||
*/
|
||||
shell_puts(" \b");
|
||||
}
|
||||
handle_backspace_key();
|
||||
break;
|
||||
|
||||
/* Carriage-return */
|
||||
@ -397,6 +508,7 @@ static bool shell_input_line(void)
|
||||
|
||||
/* Reset command length for next command processing */
|
||||
p_shell->input_line_len = 0U;
|
||||
p_shell->cursor_offset = 0U;
|
||||
break;
|
||||
|
||||
/* Line feed */
|
||||
@ -410,14 +522,7 @@ static bool shell_input_line(void)
|
||||
if (p_shell->input_line_len < SHELL_CMD_MAX_LEN) {
|
||||
/* See if a "standard" prINTable ASCII character received */
|
||||
if ((ch >= 32) && (ch <= 126)) {
|
||||
/* Add character to string */
|
||||
p_shell->buffered_line[p_shell->input_line_active][p_shell->input_line_len] = ch;
|
||||
/* Echo back the input */
|
||||
shell_puts(&p_shell->buffered_line[p_shell->input_line_active]
|
||||
[p_shell->input_line_len]);
|
||||
|
||||
/* Move to next character in string */
|
||||
p_shell->input_line_len++;
|
||||
handle_input_char(ch);
|
||||
} else {
|
||||
/* call special character handler */
|
||||
shell_handle_special_char(ch);
|
||||
@ -431,7 +536,7 @@ static bool shell_input_line(void)
|
||||
|
||||
/* Reset command length for next command processing */
|
||||
p_shell->input_line_len = 0U;
|
||||
|
||||
p_shell->cursor_offset = 0U;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ struct shell {
|
||||
int32_t input_line_active; /* Active input line index */
|
||||
|
||||
int32_t to_select_index; /* used for up/down key to select former cmds */
|
||||
uint32_t cursor_offset; /* cursor offset position from left input line */
|
||||
|
||||
struct shell_cmd *cmds; /* cmds supported */
|
||||
uint32_t cmd_count; /* Count of cmds supported */
|
||||
|
@ -42,6 +42,8 @@ char *strchr(char *s_arg, char ch);
|
||||
size_t strnlen_s(const char *str_arg, size_t maxlen_arg);
|
||||
void *memset(void *base, uint8_t v, size_t n);
|
||||
int32_t memcpy_s(void *d, size_t dmax, const void *s, size_t slen);
|
||||
void memcpy_erms(void *d, const void *s, size_t slen);
|
||||
void memcpy_erms_backwards(void *d, const void *s, size_t slen);
|
||||
int64_t strtol_deci(const char *nptr);
|
||||
uint64_t strtoul_hex(const char *nptr);
|
||||
char *strstr_s(const char *str1, size_t maxlen1, const char *str2, size_t maxlen2);
|
||||
|
Loading…
Reference in New Issue
Block a user