mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 11:29:58 +03:00
Adding CLI command pass through for MSP (#13940)
This commit is contained in:
parent
23e682c310
commit
c2900de5c1
6 changed files with 204 additions and 129 deletions
|
@ -175,9 +175,11 @@ bool cliMode = false;
|
|||
#include "cli.h"
|
||||
|
||||
static serialPort_t *cliPort = NULL;
|
||||
static bool cliInteractive = false;
|
||||
static timeMs_t cliEntryTime = 0;
|
||||
|
||||
// Space required to set array parameters
|
||||
#define CLI_IN_BUFFER_SIZE 256
|
||||
#define CLI_IN_BUFFER_SIZE 256
|
||||
#define CLI_OUT_BUFFER_SIZE 64
|
||||
|
||||
static bufWriter_t cliWriterDesc;
|
||||
|
@ -315,6 +317,7 @@ typedef enum dumpFlags_e {
|
|||
BARE = (1 << 8),
|
||||
} dumpFlags_t;
|
||||
|
||||
static void cliExit(const bool reboot);
|
||||
typedef bool printFn(dumpFlags_t dumpMask, bool equalsDefault, const char *format, ...);
|
||||
|
||||
typedef enum {
|
||||
|
@ -330,6 +333,12 @@ typedef struct serialPassthroughPort_s {
|
|||
serialPort_t *port;
|
||||
} serialPassthroughPort_t;
|
||||
|
||||
static void cliClearInputBuffer(void)
|
||||
{
|
||||
memset(cliBuffer, 0, sizeof(cliBuffer));
|
||||
bufferIndex = 0;
|
||||
}
|
||||
|
||||
static void cliWriterFlushInternal(bufWriter_t *writer)
|
||||
{
|
||||
if (writer) {
|
||||
|
@ -3581,23 +3590,17 @@ static void cliBootloader(const char *cmdName, char *cmdline)
|
|||
cliRebootEx(rebootTarget);
|
||||
}
|
||||
|
||||
static void cliExit(const char *cmdName, char *cmdline)
|
||||
static void cliExitCmd(const char *cmdName, char *cmdline)
|
||||
{
|
||||
UNUSED(cmdName);
|
||||
UNUSED(cmdline);
|
||||
|
||||
cliPrintHashLine("leaving CLI mode, unsaved changes lost");
|
||||
cliWriterFlush();
|
||||
|
||||
*cliBuffer = '\0';
|
||||
bufferIndex = 0;
|
||||
cliMode = false;
|
||||
// incase a motor was left running during motortest, clear it here
|
||||
mixerResetDisarmedMotors();
|
||||
if (strcasecmp(cmdline, "noreboot") == 0) {
|
||||
return;
|
||||
const bool reboot = strcasecmp(cmdline, "noreboot") != 0;
|
||||
if (reboot) {
|
||||
cliPrintHashLine("leaving CLI mode, unsaved changes lost");
|
||||
} else {
|
||||
cliPrintHashLine("leaving CLI mode, no reboot");
|
||||
}
|
||||
cliReboot();
|
||||
cliExit(reboot);
|
||||
}
|
||||
|
||||
#ifdef USE_GPS
|
||||
|
@ -6516,7 +6519,7 @@ const clicmd_t cmdTable[] = {
|
|||
#ifdef USE_ESCSERIAL
|
||||
CLI_COMMAND_DEF("escprog", "passthrough esc to serial", "<mode [sk/bl/ki/cc]> <index>", cliEscPassthrough),
|
||||
#endif
|
||||
CLI_COMMAND_DEF("exit", "exit command line interface and reboot (default)", "[noreboot]", cliExit),
|
||||
CLI_COMMAND_DEF("exit", "exit command line interface and reboot (default)", "[noreboot]", cliExitCmd),
|
||||
CLI_COMMAND_DEF("feature", "configure features",
|
||||
"list\r\n"
|
||||
"\t<->[name]", cliFeature),
|
||||
|
@ -6662,8 +6665,10 @@ static void cliHelp(const char *cmdName, char *cmdline)
|
|||
static void processCharacter(const char c)
|
||||
{
|
||||
if (bufferIndex && (c == '\n' || c == '\r')) {
|
||||
// enter pressed
|
||||
cliPrintLinefeed();
|
||||
if (cliInteractive) {
|
||||
// echo new line back to terminal
|
||||
cliPrintLinefeed();
|
||||
}
|
||||
|
||||
// Strip comment starting with # from line
|
||||
char *p = cliBuffer;
|
||||
|
@ -6690,25 +6695,37 @@ static void processCharacter(const char c)
|
|||
}
|
||||
if (cmd < cmdTable + ARRAYLEN(cmdTable)) {
|
||||
cmd->cliCommand(cmd->name, options);
|
||||
if (!cliMode) {
|
||||
// cli session ended
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
cliPrintError("input", "UNKNOWN COMMAND, TRY 'HELP'");
|
||||
if (cliInteractive) {
|
||||
cliPrintError("input", "UNKNOWN COMMAND, TRY 'HELP'");
|
||||
} else {
|
||||
cliPrint("ERR_CMD_NA: ");
|
||||
cliPrintLine(cliBuffer);
|
||||
}
|
||||
}
|
||||
bufferIndex = 0;
|
||||
}
|
||||
|
||||
memset(cliBuffer, 0, sizeof(cliBuffer));
|
||||
cliClearInputBuffer();
|
||||
|
||||
// 'exit' will reset this flag, so we don't need to print prompt again
|
||||
if (!cliMode) {
|
||||
return;
|
||||
// prompt if in interactive mode
|
||||
if (cliInteractive) {
|
||||
cliPrompt();
|
||||
}
|
||||
|
||||
cliPrompt();
|
||||
} else if (bufferIndex < sizeof(cliBuffer) && c >= 32 && c <= 126) {
|
||||
if (!bufferIndex && c == ' ')
|
||||
if (!bufferIndex && c == ' ') {
|
||||
return; // Ignore leading spaces
|
||||
}
|
||||
cliBuffer[bufferIndex++] = c;
|
||||
cliWrite(c);
|
||||
|
||||
// echo the character if interactive
|
||||
if (cliInteractive) {
|
||||
cliWrite(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6753,7 +6770,7 @@ static void processCharacterInteractive(const char c)
|
|||
for (; i < bufferIndex; i++)
|
||||
cliWrite(cliBuffer[i]);
|
||||
} else if (!bufferIndex && c == 4) { // CTRL-D
|
||||
cliExit("", cliBuffer);
|
||||
cliExit(true);
|
||||
return;
|
||||
} else if (c == 12) { // NewPage / CTRL-L
|
||||
// clear screen
|
||||
|
@ -6770,42 +6787,76 @@ static void processCharacterInteractive(const char c)
|
|||
}
|
||||
}
|
||||
|
||||
void cliProcess(void)
|
||||
bool cliProcess(void)
|
||||
{
|
||||
if (!cliWriter || !cliMode) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flush the buffer to get rid of any MSP data polls sent by configurator after CLI was invoked
|
||||
cliWriterFlush();
|
||||
|
||||
while (serialRxBytesWaiting(cliPort)) {
|
||||
uint8_t c = serialRead(cliPort);
|
||||
if (cliInteractive) {
|
||||
processCharacterInteractive(c);
|
||||
} else {
|
||||
// handle terminating flow control character
|
||||
if (c == 0x3 || (cmp32(millis(), cliEntryTime) > 2000)) { // CTRL-C (ETX) or 2 seconds timeout
|
||||
cliWrite(0x3); // send end of text, terminating flow control
|
||||
cliExit(false);
|
||||
return cliMode;
|
||||
}
|
||||
processCharacter(c);
|
||||
}
|
||||
}
|
||||
cliWriterFlush();
|
||||
return cliMode;
|
||||
}
|
||||
|
||||
processCharacterInteractive(c);
|
||||
static void cliExit(const bool reboot)
|
||||
{
|
||||
cliWriterFlush();
|
||||
waitForSerialPortToFinishTransmitting(cliPort);
|
||||
cliClearInputBuffer();
|
||||
cliMode = false;
|
||||
cliInteractive = false;
|
||||
// incase a motor was left running during motortest, clear it here
|
||||
mixerResetDisarmedMotors();
|
||||
|
||||
if (reboot) {
|
||||
cliReboot();
|
||||
}
|
||||
}
|
||||
|
||||
void cliEnter(serialPort_t *serialPort)
|
||||
void cliEnter(serialPort_t *serialPort, bool interactive)
|
||||
{
|
||||
cliMode = true;
|
||||
cliInteractive = interactive;
|
||||
cliPort = serialPort;
|
||||
setPrintfSerialPort(cliPort);
|
||||
cliEntryTime = millis();
|
||||
cliClearInputBuffer();
|
||||
|
||||
if (interactive) {
|
||||
setPrintfSerialPort(cliPort);
|
||||
}
|
||||
|
||||
bufWriterInit(&cliWriterDesc, cliWriteBuffer, sizeof(cliWriteBuffer), (bufWrite_t)serialWriteBufShim, serialPort);
|
||||
cliErrorWriter = cliWriter = &cliWriterDesc;
|
||||
|
||||
if (interactive) {
|
||||
#ifndef MINIMAL_CLI
|
||||
cliPrintLine("\r\nEntering CLI Mode, type 'exit' to return, or 'help'");
|
||||
cliPrintLine("\r\nEntering CLI Mode, type 'exit' to reboot, or 'help'");
|
||||
#else
|
||||
cliPrintLine("\r\nCLI");
|
||||
cliPrintLine("\r\nCLI");
|
||||
#endif
|
||||
setArmingDisabled(ARMING_DISABLED_CLI);
|
||||
|
||||
cliPrompt();
|
||||
// arming flag not released if exiting cli with no reboot for safety
|
||||
setArmingDisabled(ARMING_DISABLED_CLI);
|
||||
cliPrompt();
|
||||
|
||||
#ifdef USE_CLI_BATCH
|
||||
resetCommandBatch();
|
||||
resetCommandBatch();
|
||||
#endif
|
||||
} else {
|
||||
cliWrite(0x2); // send start of text, initiating flow control
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_CLI
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue