mirror of
https://github.com/espressif/openthread.git
synced 2026-08-19 00:49:53 +00:00
[cli] add multi-interpreter support (#13027)
This commit introduces an opaque `otCliInterpreter` type and a set of new public C CLI APIs (e.g., `otCliInterpreterInit()`, `otCliInterpreterInputLine()`) to support multiple, dynamically allocated CLI interpreters per OpenThread instance. This architecture allows applications to instantiate and manage multiple concurrent CLI sessions. Backward compatibility is preserved by retaining the original `otCli*` APIs, which now interact with a single built-in static interpreter. The `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE` configuration is also added. It enables support for the static interpreter and is enabled by default. It can be disabled to save RAM in deployments that solely use the multi-interpreter APIs.
This commit is contained in:
+108
-21
@@ -36,6 +36,8 @@
|
||||
#define OPENTHREAD_CLI_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread/error.h>
|
||||
@@ -47,17 +49,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents a CLI command.
|
||||
*/
|
||||
typedef struct otCliCommand
|
||||
{
|
||||
const char *mName; ///< A pointer to the command string.
|
||||
otError (*mCommand)(void *aContext,
|
||||
uint8_t aArgsLength,
|
||||
char *aArgs[]); ///< A function pointer to process the command.
|
||||
} otCliCommand;
|
||||
|
||||
/**
|
||||
* @addtogroup api-cli
|
||||
*
|
||||
@@ -68,7 +59,12 @@ typedef struct otCliCommand
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pointer is called to notify about Console output.
|
||||
* Opaque type for a CLI interpreter.
|
||||
*/
|
||||
typedef struct otCliInterpreter otCliInterpreter;
|
||||
|
||||
/**
|
||||
* Pointer is called to notify about CLI interpreter output.
|
||||
*
|
||||
* @param[out] aContext A user context pointer.
|
||||
* @param[in] aFormat The format string.
|
||||
@@ -80,7 +76,62 @@ typedef int (*otCliOutputCallback)(void *aContext, const char *aFormat, va_list
|
||||
OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 0);
|
||||
|
||||
/**
|
||||
* Initialize the CLI module.
|
||||
* Gets the size of the CLI interpreter object.
|
||||
*
|
||||
* @returns The size of the CLI interpreter object in bytes.
|
||||
*/
|
||||
size_t otCliInterpreterGetSize(void);
|
||||
|
||||
/**
|
||||
* Initializes a CLI interpreter.
|
||||
*
|
||||
* @param[in] aBuffer A pointer to a memory buffer for the CLI interpreter.
|
||||
* @param[in] aSize The size of the memory buffer.
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aCallback A callback method called to process CLI output.
|
||||
* @param[in] aContext A user context pointer.
|
||||
*
|
||||
* @returns A pointer to the initialized CLI interpreter, or `NULL` if @p aSize is too small.
|
||||
*/
|
||||
otCliInterpreter *otCliInterpreterInit(void *aBuffer,
|
||||
size_t aSize,
|
||||
otInstance *aInstance,
|
||||
otCliOutputCallback aCallback,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Configures whether or not the CLI interpreter outputs the prompt string.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE`.
|
||||
*
|
||||
* It is enabled by default.
|
||||
*
|
||||
* @param[in] aInterpreter A pointer to a CLI interpreter.
|
||||
* @param[in] aEnable TRUE to enable outputting the prompt, FALSE to disable.
|
||||
*/
|
||||
void otCliInterpreterSetPromptConfig(otCliInterpreter *aInterpreter, bool aEnable);
|
||||
|
||||
/**
|
||||
* Feeds input to the CLI interpreter.
|
||||
*
|
||||
* @param[in] aInterpreter A pointer to a CLI interpreter.
|
||||
* @param[in] aLine A pointer to a null-terminated string.
|
||||
*/
|
||||
void otCliInterpreterInputLine(otCliInterpreter *aInterpreter, char *aLine);
|
||||
|
||||
/**
|
||||
* Finalizes the CLI interpreter.
|
||||
*
|
||||
* @param[in] aInterpreter A pointer to a CLI interpreter.
|
||||
*/
|
||||
void otCliInterpreterFinalize(otCliInterpreter *aInterpreter);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Initialize the static CLI interpreter.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aCallback A callback method called to process CLI output.
|
||||
@@ -89,14 +140,36 @@ typedef int (*otCliOutputCallback)(void *aContext, const char *aFormat, va_list
|
||||
void otCliInit(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Is called to feed in a console input line.
|
||||
* Gets the pointer to the static CLI interpreter.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a null-terminated string.
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* @returns A pointer to the static CLI interpreter.
|
||||
*/
|
||||
void otCliInputLine(char *aBuf);
|
||||
otCliInterpreter *otCliGetStaticInterpreter(void);
|
||||
|
||||
/**
|
||||
* Set a user command table.
|
||||
* Feeds input to the static CLI interpreter.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* @param[in] aLine A pointer to a null-terminated string.
|
||||
*/
|
||||
void otCliInputLine(char *aLine);
|
||||
|
||||
/**
|
||||
* Represents a user provided CLI command entry.
|
||||
*/
|
||||
typedef struct otCliCommand
|
||||
{
|
||||
const char *mName; ///< The command string.
|
||||
otError (*mCommand)(void *aContext, uint8_t aArgsLength, char *aArgs[]); ///< Command handler function pointer.
|
||||
} otCliCommand;
|
||||
|
||||
/**
|
||||
* Set a user command table on the static CLI interpreter.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* @param[in] aUserCommands A pointer to an array with user commands.
|
||||
* @param[in] aLength The @p aUserCommands length.
|
||||
@@ -108,7 +181,11 @@ void otCliInputLine(char *aBuf);
|
||||
otError otCliSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength, void *aContext);
|
||||
|
||||
/**
|
||||
* Write a number of bytes to the CLI console as a hex string.
|
||||
* Write a number of bytes to the static CLI interpreter output as a hex string.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* This is intended for use by user-provided CLI command handlers.
|
||||
*
|
||||
* @param[in] aBytes A pointer to data which should be printed.
|
||||
* @param[in] aLength @p aBytes length.
|
||||
@@ -116,7 +193,11 @@ otError otCliSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength,
|
||||
void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
|
||||
|
||||
/**
|
||||
* Write formatted string to the CLI console
|
||||
* Write formatted string to the static CLI interpreter output.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* This is intended for use by user-provided CLI command handlers.
|
||||
*
|
||||
* @param[in] aFmt A pointer to the format string.
|
||||
* @param[in] ... A matching list of arguments.
|
||||
@@ -124,7 +205,11 @@ void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
|
||||
void otCliOutputFormat(const char *aFmt, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(1, 2);
|
||||
|
||||
/**
|
||||
* Write error code to the CLI console
|
||||
* Write a given error code as the result of previous command to the static CLI interpreter output.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*
|
||||
* This is intended for use by user-provided CLI command handlers.
|
||||
*
|
||||
* If the @p aError is `OT_ERROR_PENDING` nothing will be outputted.
|
||||
*
|
||||
@@ -133,7 +218,7 @@ void otCliOutputFormat(const char *aFmt, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CH
|
||||
void otCliAppendResult(otError aError);
|
||||
|
||||
/**
|
||||
* Callback to write the OpenThread Log to the CLI console
|
||||
* Callback to write the OpenThread Log to the static CLI interpreter output.
|
||||
*
|
||||
* @param[in] aLogLevel The log level.
|
||||
* @param[in] aLogRegion The log region.
|
||||
@@ -148,6 +233,8 @@ void otCliPlatLogv(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFo
|
||||
*
|
||||
* Available when `OPENTHREAD_CONFIG_CLI_VENDOR_COMMANDS_ENABLE` is enabled and
|
||||
* `OPENTHREAD_CONFIG_CLI_MAX_USER_CMD_ENTRIES` is greater than 1.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE`.
|
||||
*/
|
||||
extern void otCliVendorSetUserCommands(void);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (595)
|
||||
#define OPENTHREAD_API_VERSION (596)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
+42
-7
@@ -71,9 +71,6 @@
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
Interpreter *Interpreter::sInterpreter = nullptr;
|
||||
static OT_DEFINE_ALIGNED_VAR(sInterpreterRaw, sizeof(Interpreter), uint64_t);
|
||||
|
||||
Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext)
|
||||
: OutputImplementer(aCallback, aContext)
|
||||
, Utils(aInstance, *this)
|
||||
@@ -8504,11 +8501,49 @@ void Interpreter::HandleWakeupResult(otError aError) { OutputResult(aError); }
|
||||
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
void Interpreter::Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
|
||||
{
|
||||
Instance *instance = static_cast<Instance *>(aInstance);
|
||||
size_t Interpreter::GetSize(void) { return sizeof(Interpreter); }
|
||||
|
||||
Interpreter::sInterpreter = new (&sInterpreterRaw) Interpreter(instance, aCallback, aContext);
|
||||
Interpreter *Interpreter::Init(void *aBuffer,
|
||||
size_t aSize,
|
||||
otInstance *aInstance,
|
||||
otCliOutputCallback aCallback,
|
||||
void *aContext)
|
||||
{
|
||||
Interpreter *interpreter = nullptr;
|
||||
Instance *instance = static_cast<Instance *>(aInstance);
|
||||
|
||||
VerifyOrExit(aSize >= sizeof(Interpreter));
|
||||
interpreter = new (aBuffer) Interpreter(instance, aCallback, aContext);
|
||||
|
||||
exit:
|
||||
return interpreter;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
|
||||
Interpreter *Interpreter::sInterpreter = nullptr;
|
||||
|
||||
static OT_DEFINE_ALIGNED_VAR(sInterpreterRaw, sizeof(Interpreter), uint64_t);
|
||||
|
||||
void Interpreter::Init(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
|
||||
{
|
||||
sInterpreter = Init(&sInterpreterRaw, sizeof(sInterpreterRaw), aInstance, aCallback, aContext);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Interpreter::Finalize(void)
|
||||
{
|
||||
mTimer.Stop();
|
||||
|
||||
#if (OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK
|
||||
otIp6SetReceiveCallback(GetInstancePtr(), nullptr, nullptr);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
otDiagSetOutputCallback(GetInstancePtr(), nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
this->~Interpreter();
|
||||
}
|
||||
|
||||
void Interpreter::OutputPrompt(void)
|
||||
|
||||
+44
-7
@@ -86,6 +86,10 @@
|
||||
#include "common/type_traits.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
typedef struct otCliInterpreter
|
||||
{
|
||||
} otCliInterpreter;
|
||||
|
||||
namespace ot {
|
||||
|
||||
/**
|
||||
@@ -103,7 +107,7 @@ extern "C" void otCliOutputFormat(const char *aFmt, ...);
|
||||
/**
|
||||
* Implements the CLI interpreter.
|
||||
*/
|
||||
class Interpreter : public OutputImplementer, public Utils
|
||||
class Interpreter : public otCliInterpreter, public OutputImplementer, public Utils
|
||||
{
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
friend class Ba;
|
||||
@@ -138,34 +142,65 @@ public:
|
||||
*/
|
||||
explicit Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext);
|
||||
|
||||
#if OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
/**
|
||||
* Returns a reference to the interpreter object.
|
||||
* Returns a reference to the static CLI interpreter.
|
||||
*
|
||||
* @returns A reference to the interpreter object.
|
||||
* @returns A reference to the static CLI interpreter.
|
||||
*/
|
||||
static Interpreter &GetInterpreter(void)
|
||||
{
|
||||
OT_ASSERT(sInterpreter != nullptr);
|
||||
|
||||
return *sInterpreter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Console interpreter.
|
||||
* Initializes the static CLI interpreter.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aCallback A pointer to a callback method.
|
||||
* @param[in] aContext A pointer to a user context.
|
||||
*/
|
||||
static void Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
|
||||
static void Init(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Returns whether the interpreter is initialized.
|
||||
* Returns whether the static CLI interpreter is initialized.
|
||||
*
|
||||
* @returns Whether the interpreter is initialized.
|
||||
*/
|
||||
static bool IsInitialized(void) { return sInterpreter != nullptr; }
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
|
||||
/**
|
||||
* Gets the size of the CLI interpreter object.
|
||||
*
|
||||
* @returns The size of the CLI interpreter object in bytes.
|
||||
*/
|
||||
static size_t GetSize(void);
|
||||
|
||||
/**
|
||||
* Initializes a CLI interpreter.
|
||||
*
|
||||
* @param[in] aBuffer A pointer to a memory buffer for the CLI interpreter.
|
||||
* @param[in] aSize The size of the memory buffer.
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aCallback A callback method called to process CLI output.
|
||||
* @param[in] aContext A user context pointer.
|
||||
*
|
||||
* @returns A pointer to the initialized CLI interpreter, or `nullptr` if @p aSize is too small.
|
||||
*/
|
||||
static Interpreter *Init(void *aBuffer,
|
||||
size_t aSize,
|
||||
otInstance *aInstance,
|
||||
otCliOutputCallback aCallback,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Finalizes the CLI interpreter.
|
||||
*/
|
||||
void Finalize(void);
|
||||
|
||||
/**
|
||||
* Interprets a CLI command.
|
||||
*
|
||||
@@ -197,7 +232,9 @@ public:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#if OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
static Interpreter *sInterpreter;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kIndentSize = 4;
|
||||
|
||||
+38
-2
@@ -38,16 +38,50 @@
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
extern "C" size_t otCliInterpreterGetSize(void) { return Interpreter::GetSize(); }
|
||||
|
||||
extern "C" otCliInterpreter *otCliInterpreterInit(void *aBuffer,
|
||||
size_t aSize,
|
||||
otInstance *aInstance,
|
||||
otCliOutputCallback aCallback,
|
||||
void *aContext)
|
||||
{
|
||||
return Interpreter::Init(aBuffer, aSize, aInstance, aCallback, aContext);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE
|
||||
extern "C" void otCliInterpreterSetPromptConfig(otCliInterpreter *aInterpreter, bool aEnable)
|
||||
{
|
||||
static_cast<Interpreter *>(aInterpreter)->SetPromptConfig(aEnable);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" void otCliInterpreterInputLine(otCliInterpreter *aInterpreter, char *aLine)
|
||||
{
|
||||
static_cast<Interpreter *>(aInterpreter)->ProcessLine(aLine);
|
||||
}
|
||||
|
||||
extern "C" void otCliInterpreterFinalize(otCliInterpreter *aInterpreter)
|
||||
{
|
||||
static_cast<Interpreter *>(aInterpreter)->Finalize();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
|
||||
extern "C" void otCliInit(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
|
||||
{
|
||||
Interpreter::Initialize(aInstance, aCallback, aContext);
|
||||
Interpreter::Init(aInstance, aCallback, aContext);
|
||||
|
||||
#if OPENTHREAD_CONFIG_CLI_VENDOR_COMMANDS_ENABLE && OPENTHREAD_CONFIG_CLI_MAX_USER_CMD_ENTRIES > 1
|
||||
otCliVendorSetUserCommands();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void otCliInputLine(char *aBuf) { Interpreter::GetInterpreter().ProcessLine(aBuf); }
|
||||
extern "C" otCliInterpreter *otCliGetStaticInterpreter(void) { return &Interpreter::GetInterpreter(); }
|
||||
|
||||
extern "C" void otCliInputLine(char *aLine) { Interpreter::GetInterpreter().ProcessLine(aLine); }
|
||||
|
||||
extern "C" otError otCliSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength, void *aContext)
|
||||
{
|
||||
@@ -88,5 +122,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace ot
|
||||
|
||||
@@ -47,6 +47,21 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
*
|
||||
* Define as 1 to enable the static CLI interpreter.
|
||||
*
|
||||
* This configuration option enables the static CLI interpreter, allowing the CLI module to statically allocate and
|
||||
* provide a single interpreter instance.
|
||||
*
|
||||
* This is intended to provide backward compatibility with the original `otCli*` APIs. It can be disabled to save RAM
|
||||
* if the static CLI interpreter is not needed.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE
|
||||
#define OPENTHREAD_CONFIG_CLI_STATIC_INTERPRETER_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user