123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- /*
- * Copyright (c) 2024, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include "FreeRTOS.h"
- #include "task.h"
- #include "event_groups.h"
- #include "csh.h"
- #include "usbd_core.h"
- #include "usbd_adb.h"
- #include "chry_ringbuffer.h"
- static chry_ringbuffer_t shell_rb;
- static uint8_t mempool[1024];
- #ifndef task_repl_PRIORITY
- #define task_repl_PRIORITY (configMAX_PRIORITIES - 4U)
- #endif
- #ifndef task_exec_PRIORITY
- #define task_exec_PRIORITY (configMAX_PRIORITIES - 5U)
- #endif
- static chry_shell_t csh;
- static volatile bool login = false;
- static StaticTask_t task_buffer_repl;
- static StaticTask_t task_buffer_exec;
- static StackType_t task_stack_repl[1024];
- static StackType_t task_stack_exec[1024];
- static TaskHandle_t task_hdl_repl = NULL;
- static TaskHandle_t task_hdl_exec = NULL;
- static EventGroupHandle_t event_hdl;
- static StaticEventGroup_t event_grp;
- void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
- {
- chry_ringbuffer_write(&shell_rb, data, len);
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- xEventGroupSetBitsFromISR(event_hdl, 0x10, &xHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
- }
- void usbd_adb_notify_write_done(void)
- {
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- xEventGroupSetBitsFromISR(event_hdl, 0x20, &xHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
- }
- static uint16_t csh_sput_cb(chry_readline_t *rl, const void *data, uint16_t size)
- {
- (void)rl;
- if (!usb_device_is_configured(0)) {
- return size;
- }
- if (usbd_adb_can_write() && size) {
- usbd_abd_write(ADB_SHELL_LOALID, data, size);
- xEventGroupWaitBits(event_hdl, 0x20, pdTRUE, pdFALSE, portMAX_DELAY);
- }
- return size;
- }
- static uint16_t csh_sget_cb(chry_readline_t *rl, void *data, uint16_t size)
- {
- (void)rl;
- return chry_ringbuffer_read(&shell_rb, data, size);
- }
- static void wait_char(void)
- {
- EventBits_t event;
- wait:
- /* In order to lock the log from being disrupted , wait for REPL task execution to complete */
- event = xEventGroupWaitBits(event_hdl, (0x10 | 0x01 | 0x04), pdTRUE, pdFALSE, portMAX_DELAY);
- if ((event & 0x10) == 0) {
- if (event & 0x01) {
- chry_readline_erase_line(&csh.rl);
- xEventGroupSetBits(event_hdl, 0x02);
- }
- if (event & 0x04) {
- chry_readline_edit_refresh(&csh.rl);
- xEventGroupSetBits(event_hdl, 0x08);
- }
- goto wait;
- }
- }
- static void task_repl(void *param)
- {
- (void)param;
- int ret;
- volatile uint8_t *pexec = (void *)&csh.exec;
- for (;;) {
- restart:
- if (login) {
- goto repl;
- } else {
- }
- ret = csh_login(&csh);
- if (ret == 0) {
- login = true;
- } else if (ret == 1) {
- /*!< no enough char */
- wait_char();
- continue;
- } else {
- continue;
- }
- repl:
- ret = chry_shell_task_repl(&csh);
- if (ret == -1) {
- /*!< error */
- goto restart;
- } else if (ret == 1) {
- /*!< no enough char */
- wait_char();
- } else {
- /*!< restart */
- }
- /*!< check flag */
- if (*pexec == CSH_STATUS_EXEC_DONE) {
- *pexec = CSH_STATUS_EXEC_IDLE;
- chry_readline_auto_refresh(&csh.rl, true);
- chry_readline_ignore(&csh.rl, false);
- chry_readline_edit_refresh(&csh.rl);
- }
- if (login == false) {
- chry_readline_erase_line(&csh.rl);
- csh.rl.noblock = false;
- }
- }
- }
- static void task_exec(void *param)
- {
- (void)param;
- /*!< execute shell command */
- chry_shell_task_exec(&csh);
- /*!< notify REPL task execute done */
- xEventGroupSetBits(event_hdl, 0x10);
- /*!< wait for REPL task delete */
- vTaskSuspend(NULL);
- }
- int chry_shell_port_create_context(chry_shell_t *csh, int argc, const char **argv)
- {
- volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
- (void)csh;
- (void)argc;
- (void)argv;
- if (*p_task_hdl_exec != NULL) {
- vTaskDelete(*p_task_hdl_exec);
- }
- *p_task_hdl_exec = xTaskCreateStatic(task_exec, "task_exec", 1024U, NULL, task_exec_PRIORITY, task_stack_exec, &task_buffer_exec);
- return 0;
- }
- void chry_shell_port_default_handler(chry_shell_t *csh, int sig)
- {
- volatile uint8_t *pexec = (void *)&csh->exec;
- volatile TaskHandle_t *p_task_hdl_exec = (void *)&task_hdl_exec;
- switch (sig) {
- case CSH_SIGINT:
- case CSH_SIGQUIT:
- case CSH_SIGKILL:
- case CSH_SIGTERM:
- break;
- default:
- return;
- }
- /*!< force delete task */
- if (*p_task_hdl_exec != NULL) {
- vTaskDelete(task_hdl_exec);
- *p_task_hdl_exec = NULL;
- }
- switch (sig) {
- case CSH_SIGINT:
- csh->rl.sput(&csh->rl, "^SIGINT" CONFIG_CSH_NEWLINE, sizeof("^SIGINT" CONFIG_CSH_NEWLINE) - 1);
- break;
- case CSH_SIGQUIT:
- csh->rl.sput(&csh->rl, "^SIGQUIT" CONFIG_CSH_NEWLINE, sizeof("^SIGQUIT" CONFIG_CSH_NEWLINE) - 1);
- break;
- case CSH_SIGKILL:
- csh->rl.sput(&csh->rl, "^SIGKILL" CONFIG_CSH_NEWLINE, sizeof("^SIGKILL" CONFIG_CSH_NEWLINE) - 1);
- break;
- case CSH_SIGTERM:
- csh->rl.sput(&csh->rl, "^SIGTERM" CONFIG_CSH_NEWLINE, sizeof("^SIGTERM" CONFIG_CSH_NEWLINE) - 1);
- break;
- default:
- return;
- }
- *pexec = CSH_STATUS_EXEC_IDLE;
- chry_readline_auto_refresh(&csh->rl, true);
- chry_readline_ignore(&csh->rl, false);
- chry_readline_edit_refresh(&csh->rl);
- }
- int shell_init(bool need_login)
- {
- chry_shell_init_t csh_init;
- if (chry_ringbuffer_init(&shell_rb, mempool, sizeof(mempool))) {
- return -1;
- }
- if (need_login) {
- login = false;
- } else {
- login = true;
- }
- /*!< I/O callback */
- csh_init.sput = csh_sput_cb;
- csh_init.sget = csh_sget_cb;
- #if defined(CONFIG_CSH_SYMTAB) && CONFIG_CSH_SYMTAB
- extern const int __fsymtab_start;
- extern const int __fsymtab_end;
- extern const int __vsymtab_start;
- extern const int __vsymtab_end;
- /*!< get table from ld symbol */
- csh_init.command_table_beg = &__fsymtab_start;
- csh_init.command_table_end = &__fsymtab_end;
- csh_init.variable_table_beg = &__vsymtab_start;
- csh_init.variable_table_end = &__vsymtab_end;
- #endif
- #if defined(CONFIG_CSH_PROMPTEDIT) && CONFIG_CSH_PROMPTEDIT
- static char csh_prompt_buffer[128];
- /*!< set prompt buffer */
- csh_init.prompt_buffer = csh_prompt_buffer;
- csh_init.prompt_buffer_size = sizeof(csh_prompt_buffer);
- #endif
- #if defined(CONFIG_CSH_HISTORY) && CONFIG_CSH_HISTORY
- static char csh_history_buffer[128];
- /*!< set history buffer */
- csh_init.history_buffer = csh_history_buffer;
- csh_init.history_buffer_size = sizeof(csh_history_buffer);
- #endif
- #if defined(CONFIG_CSH_LNBUFF_STATIC) && CONFIG_CSH_LNBUFF_STATIC
- static char csh_line_buffer[128];
- /*!< set linebuffer */
- csh_init.line_buffer = csh_line_buffer;
- csh_init.line_buffer_size = sizeof(csh_line_buffer);
- #endif
- csh_init.uid = 0;
- csh_init.user[0] = "cherry";
- /*!< The port hash function is required,
- and the strcmp attribute is used weakly by default,
- int chry_shell_port_hash_strcmp(const char *hash, const char *str); */
- csh_init.hash[0] = "12345678"; /*!< If there is no password, set to NULL */
- csh_init.host = "cherryadb";
- csh_init.user_data = NULL;
- int ret = chry_shell_init(&csh, &csh_init);
- if (ret) {
- return -1;
- }
- task_hdl_exec = NULL;
- event_hdl = xEventGroupCreateStatic(&event_grp);
- task_hdl_repl = xTaskCreateStatic(task_repl, "task_repl", 1024U, NULL, task_repl_PRIORITY, task_stack_repl, &task_buffer_repl);
- return 0;
- }
- void shell_lock(void)
- {
- xEventGroupSetBits(event_hdl, 0x01);
- xEventGroupWaitBits(event_hdl, 0x02, pdTRUE, pdTRUE, portMAX_DELAY);
- }
- void shell_unlock(void)
- {
- xEventGroupSetBits(event_hdl, 0x04);
- xEventGroupWaitBits(event_hdl, 0x08, pdTRUE, pdTRUE, portMAX_DELAY);
- }
- static int csh_exit(int argc, char **argv)
- {
- (void)argc;
- (void)argv;
- usbd_adb_close(ADB_SHELL_LOALID);
- return 0;
- }
- CSH_SCMD_EXPORT_ALIAS(csh_exit, exit, );
- #define __ENV_PATH "/sbin:/bin"
- const char ENV_PATH[] = __ENV_PATH;
- CSH_RVAR_EXPORT(ENV_PATH, PATH, sizeof(__ENV_PATH));
- #define __ENV_ZERO ""
- const char ENV_ZERO[] = __ENV_ZERO;
- CSH_RVAR_EXPORT(ENV_ZERO, ZERO, sizeof(__ENV_ZERO));
|