15static const char*
TAG =
"CMDREGS";
32 authCheck_ = authCheck;
47 for (
size_t i = 0; i < count_; i++) {
48 if (strcasecmp(commands_[i].
name, cmd.
name) == 0) {
54 commands_[count_++] = cmd;
65 if (!moduleName)
return;
68 for (
size_t readIdx = 0; readIdx < count_; readIdx++) {
69 if (commands_[readIdx].moduleName &&
70 strcmp(commands_[readIdx].moduleName, moduleName) == 0) {
74 if (writeIdx != readIdx) {
75 commands_[writeIdx] = commands_[readIdx];
88 lineInterceptor_ = interceptor;
92 byteInterceptor_ = interceptor;
96 return byteInterceptor_;
105 if (!line || !*line)
return false;
108 if (lineInterceptor_ && lineInterceptor_(line)) {
115 while (*line && !isspace(*line) && cmdLen <
sizeof(cmdBuf) - 1) {
116 cmdBuf[cmdLen++] = *line++;
118 cmdBuf[cmdLen] =
'\0';
121 while (*line && isspace(*line)) line++;
123#if FEATURE_SECURE_SERIAL
127 if (
pm.isBadgeBlocked()) {
128 if (strcasecmp(cmdBuf,
"PING") != 0) {
129 if (
pm.isLockoutActive()) {
130 uint32_t remainingSec =
pm.getLockoutRemainingMs() / 1000;
132 (
unsigned long)remainingSec);
143 bool isAllowedWithoutAuth = (strcasecmp(cmdBuf,
"PING") == 0 ||
144 strcasecmp(cmdBuf,
"AUTH") == 0 ||
145 strcasecmp(cmdBuf,
"VERSION") == 0 ||
146 strcasecmp(cmdBuf,
"HELP") == 0);
147 if (!isAllowedWithoutAuth && authCheck_ && !authCheck_()) {
148 Console::printf(
"ERROR: Not authenticated. Use AUTH <pin> to login.\r\n");
155 for (
size_t i = 0; i < count_; i++) {
156 if (strcasecmp(commands_[i].
name, cmdBuf) == 0) {
159 if (commands_[i].requiresAuth && authCheck_ && !authCheck_()) {
160 Console::printf(
"ERROR: Authentication required. Use AUTH <pin> first.\r\n");
163 if (commands_[i].handler) {
164 commands_[i].handler(line);
167 if (onCommandExecuted_) {
168 onCommandExecuted_();
187 const char* currentModule =
nullptr;
189 for (
size_t i = 0; i < count_; i++) {
190 const char* module = commands_[i].moduleName ? commands_[i].moduleName :
"system";
192 if (!currentModule || strcmp(currentModule, module) != 0) {
194 currentModule =
module;
199 commands_[i].help ? commands_[i].help :
"");
201 if (!commands_[i].subCommands)
continue;
202 for (
const SubCommand* e = commands_[i].subCommands; e->
name; ++e) {
204 if (e->args && *e->args) {
205 std::snprintf(head,
sizeof(head),
"%s %s", e->name, e->args);
207 std::snprintf(head,
sizeof(head),
"%s", e->name);
210 head, e->help ? e->help :
"");
232 onCommandExecuted_ = callback;
238 bool (*authCheck_)() =
nullptr;
239 void (*onCommandExecuted_)() =
nullptr;
250 return *g_commandRegistry;
char name[cdc::hal::ISecureElement::RMEM_NAME_LEN]
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_I(tag, fmt,...)
static PinManager & instance()
Returns singleton PIN manager instance.
ByteInterceptor getByteInterceptor() const override
bool processCommand(const char *line) override
Parses and executes one command line.
void showHelp() override
Prints grouped help for all registered commands.
void setLineInterceptor(LineInterceptor interceptor) override
Sets optional line interceptor for multiline modes.
void setOnCommandExecuted(void(*callback)()) override
Sets callback fired after successful command execution.
void unregisterModule(const char *moduleName) override
Unregisters all commands belonging to one module.
void setAuthProvider(bool(*authCheck)()) override
Sets external authentication status provider.
bool registerCommand(const Command &cmd) override
Registers a command in the dispatch table.
void setByteInterceptor(ByteInterceptor interceptor) override
size_t getCommandCount() const override
Returns count of currently registered commands.
static void flush()
Flushes pending console output.
static void printf(const char *format,...) __attribute__((format(printf
Prints formatted text to console.
void(*)(uint8_t byte) ByteInterceptor
bool(*)(const char *line) LineInterceptor
constexpr size_t kSubCommandHeadBufSize
Buffer size for the "<name> <args>" column built during HELP rendering.
ICommandRegistry & getCommandRegistry()
Returns singleton command-registry interface.
static constexpr size_t MAX_COMMANDS
Maximum number of commands that can be registered.
const char * moduleName
Module that registered the command (used for HELP grouping).
const char * name
Top-level command (e.g. "TOTP" or "PING").
const char * name
Sub-command keyword, e.g. "LIST". nullptr terminates the array.