diff --git a/include/openthread/cli.h b/include/openthread/cli.h index e6b5575d1..84606c2b5 100644 --- a/include/openthread/cli.h +++ b/include/openthread/cli.h @@ -43,6 +43,16 @@ extern "C" { #endif +/** + * This structure represents a CLI command. + * + */ +typedef struct otCliCommand +{ + const char *mName; ///< A pointer to the command string. + void (*mCommand)(int argc, char *argv[]); ///< A function pointer to process the command. +} otCliCommand; + /** * @addtogroup api-cli * @@ -93,6 +103,37 @@ void otCliConsoleInputLine(char *aBuf, uint16_t aBufLength); */ void otCliUartInit(otInstance *aInstance); +/** + * Set a user command table. + * + * @param[in] aUserCommands A pointer to an array with user commands. + * @param[in] aLength @p aUserCommands length. + */ +void otCliUartSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength); + +/** + * Write a number of bytes to the CLI console as a hex string. + * + * @param[in] aBytes A pointer to data which should be printed. + * @param[in] aLength @p aBytes length. + */ +void otCliUartOutputBytes(const uint8_t *aBytes, uint8_t aLength); + +/** + * Write formatted string the CLI console + * + * @param[in] aFmt A pointer to the format string. + * @param[in] ... A matching list of arguments. + */ +void otCliUartOutputFormat(const char *aFmt, ...); + +/** + * Write error code the CLI console + * + * @param[in] aError Error code value. + */ +void otCliUartAppendResult(otError aError); + /** * Callback to write the OpenThread Log to the CLI console * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index a801517cb..0135b46e2 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -246,6 +246,8 @@ Interpreter::Interpreter(otInstance *aInstance): #if OPENTHREAD_ENABLE_APPLICATION_COAP mCoap(*this), #endif + mUserCommands(NULL), + mUserCommandsLength(0), mServer(NULL), #ifdef OTDLL mApiInstance(otApiInit()), @@ -378,6 +380,11 @@ void Interpreter::ProcessHelp(int argc, char *argv[]) mServer->OutputFormat("%s\r\n", sCommands[i].mName); } + for (unsigned int i = 0; i < mUserCommandsLength; i++) + { + mServer->OutputFormat("%s\r\n", mUserCommands[i].mName); + } + OT_UNUSED_VARIABLE(argc); OT_UNUSED_VARIABLE(argv); } @@ -3261,10 +3268,23 @@ void Interpreter::ProcessLine(char *aBuf, uint16_t aBufLength, Server &aServer) } } - // Error prompt for unsupported commands + // Check user defined commands if built-in command + // has not been found if (i == sizeof(sCommands) / sizeof(sCommands[0])) { - AppendResult(OT_ERROR_PARSE); + for (i = 0; i < mUserCommandsLength; i++) + { + if (strcmp(cmd, mUserCommands[i].mName) == 0) + { + mUserCommands[i].mCommand(argc, argv); + break; + } + } + + if (i == mUserCommandsLength) + { + AppendResult(OT_ERROR_PARSE); + } } exit: @@ -3378,6 +3398,12 @@ void Interpreter::HandleDiagnosticGetResponse(Message &aMessage, const Ip6::Mess } #endif +void Interpreter::SetUserCommands(const otCliCommand *aCommands, uint8_t aLength) +{ + mUserCommands = aCommands; + mUserCommandsLength = aLength; +} + Interpreter &Interpreter::GetOwner(const Context &aContext) { #if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 9ffbb4506..7ccb884cc 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include "cli/cli_server.hpp" #include "cli/cli_udp_example.hpp" @@ -150,6 +151,29 @@ public: */ static int Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength); + /** + * Write error code the CLI console + * + * @param[in] aError Error code value. + */ + void AppendResult(otError error) const; + + /** + * Write a number of bytes to the CLI console as a hex string. + * + * @param[in] aBytes A pointer to data which should be printed. + * @param[in] aLength @p aBytes length. + */ + void OutputBytes(const uint8_t *aBytes, uint8_t aLength) const; + + /** + * Set a user command table. + * + * @param[in] aUserCommands A pointer to an array with user commands. + * @param[in] aLength @p aUserCommands length. + */ + void SetUserCommands(const otCliCommand *aCommands, uint8_t aLength); + private: enum { @@ -158,8 +182,6 @@ private: kDefaultJoinerTimeout = 120, ///< Default timeout for Joiners, in seconds. }; - void AppendResult(otError error) const; - void OutputBytes(const uint8_t *aBytes, uint8_t aLength) const; void ProcessHelp(int argc, char *argv[]); void ProcessAutoStart(int argc, char *argv[]); @@ -354,6 +376,8 @@ private: #endif // OPENTHREAD_ENABLE_APPLICATION_COAP static const struct Command sCommands[]; + const otCliCommand *mUserCommands; + uint8_t mUserCommandsLength; Server *mServer; diff --git a/src/cli/cli_uart.cpp b/src/cli/cli_uart.cpp index b7e20dfb0..8023373a5 100644 --- a/src/cli/cli_uart.cpp +++ b/src/cli/cli_uart.cpp @@ -43,7 +43,6 @@ #include #include #include - #include "cli/cli.hpp" #include "common/code_utils.hpp" #include "common/encoding.hpp" @@ -70,6 +69,29 @@ extern "C" void otCliUartInit(otInstance *aInstance) Uart::sUartServer = new(&sCliUartRaw) Uart(aInstance); } +extern "C" void otCliUartSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength) +{ + Uart::sUartServer->GetInterpreter().SetUserCommands(aUserCommands, aLength); +} + +extern "C" void otCliUartOutputBytes(const uint8_t *aBytes, uint8_t aLength) +{ + Uart::sUartServer->GetInterpreter().OutputBytes(aBytes, aLength); +} + +extern "C" void otCliUartOutputFormat(const char *aFmt, ...) +{ + va_list aAp; + va_start(aAp, aFmt); + Uart::sUartServer->OutputFormatV(aFmt, aAp); + va_end(aAp); +} + +extern "C" void otCliUartAppendResult(otError aError) +{ + Uart::sUartServer->GetInterpreter().AppendResult(aError); +} + Uart::Uart(otInstance *aInstance): mInterpreter(aInstance) {