/* * Copyright (c) 2019-2022, Erich Styger * * SPDX-License-Identifier: BSD-3-Clause */ #include "platform.h" #include "Shell.h" #include "McuShell.h" #include "McuRTT.h" #include "McuArmTools.h" #include "McuShellUart.h" #include "McuLog.h" #include "McuUtility.h" #include "MotOffsetTable.h" #include "minIni/McuMinINI.h" #include "minIni/McuFlash.h" #include "nvmc.h" #define SHELL_CMD_ELEM_SIZE (sizeof(Shell_cmd_s)) static QueueHandle_t shellCmdQueue; static void vQueueShellCmd(Shell_cmd_s shellCmd){ if(xQueueSendToBack(shellCmdQueue, &shellCmd, pdMS_TO_TICKS(100)) != pdPASS){ McuLog_warn("Failed adding shell cmd to queue, maybe full?"); } } static uint8_t ParseCommand(const uint8_t *cmd, bool *handled, McuShell_ConstStdIOType *io){ if (McuUtility_strcmp((char*)cmd, McuShell_CMD_HELP)==0) { McuShell_SendStr((unsigned char*)"\r\n", io->stdOut); McuShell_SendStr((unsigned char*)McuShell_DASH_LINE, io->stdOut); McuShell_SendStr((unsigned char*)"\r\n", io->stdOut); McuShell_SendHelpStr((unsigned char*)"SplitFlap Help", (const unsigned char*)"Group of SplitFlap commands\r\n", io->stdOut); McuShell_SendHelpStr((unsigned char*)" help", (const unsigned char*)"Print help this message\r\n", io->stdOut); McuShell_SendHelpStr((unsigned char*)SHELL_CMD_IDENTIFY_SF, (const unsigned char*)" (uint8_t) (uint8_t)\r\n", io->stdOut); McuShell_SendHelpStr((unsigned char*)SHELL_CMD_POWEROFF_RPI, (const unsigned char*)"power of the raspberry pi\r\n", io->stdOut); McuShell_SendHelpStr((unsigned char*)SHELL_CMD_INIT_ALL_SF, (const unsigned char*)"init all Splitflaps\r\n", io->stdOut); *handled = TRUE; return ERR_OK; } else if(McuUtility_strncmp((char*)cmd, SHELL_CMD_IDENTIFY_SF, sizeof(SHELL_CMD_IDENTIFY_SF)-1) == 0){ int32_t hwId = 0; int32_t setupId = 0; *handled = TRUE; cmd += sizeof(SHELL_CMD_IDENTIFY_SF)-1; if(McuUtility_xatoi(&cmd, &setupId) == ERR_OK){ // validate param if(setupId > NUM_FLAPS){ return ERR_FAILED; } }else{ return ERR_FAILED; } // second param cmd++; if(McuUtility_xatoi(&cmd, &hwId) == ERR_OK){ // validate param int32_t offset = 0; if(MotOffset_Get(hwId, &offset) != ERR_OK){ return ERR_FAILED; } }else{ return ERR_FAILED; } Shell_cmd_s shellCmd = {.shellCmd = Shell_Identify_SF, .numberOfParams = 2, .params = {hwId,setupId}}; //Shell_cmd_s shellCmd = {.shellCmd = Shell_Identify_SF, .value1 = setupId, .value2 = hwId}; vQueueShellCmd(shellCmd); } else if(McuUtility_strcmp((char*)cmd,SHELL_CMD_POWEROFF_RPI) == 0){ // shutown rpi *handled = TRUE; Shell_cmd_s shellCmd = {.shellCmd = Shell_Powerof_rpi, .numberOfParams = 0}; vQueueShellCmd(shellCmd); }else if(McuUtility_strcmp((char*)cmd, SHELL_CMD_INIT_ALL_SF) == 0){ *handled = TRUE; Shell_cmd_s shellCmd = {.shellCmd = Shell_Init_All_SF, .numberOfParams = 0}; vQueueShellCmd(shellCmd); }else if(McuUtility_strncmp((char*)cmd,SHELL_CMD_DISPLAY_STRING,sizeof(SHELL_CMD_DISPLAY_STRING)-1) == 0){ *handled = TRUE; Shell_cmd_s shellCmd = {.shellCmd = Shell_Display_String_SF, .numberOfParams = NUM_FLAPS, .params = {0}}; cmd += sizeof(SHELL_CMD_DISPLAY_STRING)-1; if(SHELL_stringToInt32ArrayForSFCMD(&cmd, shellCmd.params, NUM_FLAPS) != ERR_OK){ return ERR_FAILED; } vQueueShellCmd(shellCmd); } return ERR_OK; } uint8_t SHELL_stringToInt32ArrayForSFCMD(const unsigned char **str, int32_t* res, int8_t sizeRes){ uint8_t c = 0; while(**str == ' '){ (*str)++; // skip leading spaces } c = **str; while(c != '\0' && sizeRes>0){ sizeRes--; if(c <= '9' && c >= '0'){ // its a number *res = (int32_t)c; res++; }else if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){ // its a char if(c >= 'a' && c <= 'z'){ *res = (int32_t)c-0x20; }else{ *res = (int32_t)c; } res++; } else if(c == '!' || c == '?' || c == ':' || c == ' '){ // special character allowed by SF *res = (int32_t)c; res++; } else{ return ERR_RANGE; } c = *(++(*str)); } return ERR_OK; } uint8_t SHELL_Int32ArrayToStringForSF(int32_t* intArray, int8_t size, char *str){ for(uint8_t i = 0; i < size; i++){ if(intArray[i] > 127 || intArray[i] < 0){ return ERR_RANGE; } *str = (char)intArray[i]; if(!((*str <= '9' && *str >= '0') || (*str >= 'A' && *str <= 'Z') || *str == '!' || *str == '?' || *str == ':' || *str == ' ')){ return ERR_RANGE; } str++; } return ERR_OK; } static const McuShell_ParseCommandCallback CmdParserTable[] = { ParseCommand, McuShell_ParseCommand, McuRTOS_ParseCommand, McuFlash_ParseCommand, ini_ParseCommand, McuMinINI_ParseCommand, NVMC_ParseCommand, NULL /* Sentinel */ }; typedef struct { McuShell_ConstStdIOType *stdio; unsigned char *buf; size_t bufSize; } SHELL_IODesc; static const SHELL_IODesc ios[] = { {&McuShellUart_stdio, McuShellUart_DefaultShellBuffer, sizeof(McuShellUart_DefaultShellBuffer)}, {&McuRTT_stdio, McuRTT_DefaultShellBuffer, sizeof(McuRTT_DefaultShellBuffer)}, // {&USB_CdcStdio, USB_CdcDefaultShellBuffer, sizeof(USB_CdcDefaultShellBuffer)}, }; QueueHandle_t SHELL_GetShellCmdQueueHandle() { return shellCmdQueue; } void SHELL_SendChar(unsigned char ch) { for(int i=0;istdOut); } } uint8_t SHELL_ParseCommandIO(const unsigned char *command, McuShell_ConstStdIOType *io, bool silent) { if (io==NULL) { /* use a default */ io = McuShell_GetStdio(); } return McuShell_ParseWithCommandTableExt(command, io, CmdParserTable, silent); } void SHELL_SendString(const unsigned char *str) { for(int i=0;istdOut); } } static void ShellTask(void *pv) { int i; McuLog_info("Shell task started"); for(i=0;i