245 lines
6.8 KiB
C
245 lines
6.8 KiB
C
/* SPDX-License-Identifier: GPL-3.0-only */
|
|
/* Full-line linenoise completion for nested project console commands. */
|
|
|
|
#include "console_completion.h"
|
|
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "esp_console.h"
|
|
#include "linenoise/linenoise.h"
|
|
|
|
/* Keep full-line candidate strings grouped by their registered root command. */
|
|
static const char *const s_completion_candidates[] = {
|
|
/* Hardware debug commands and safe fixed arguments. */
|
|
"debug transceiver",
|
|
"debug transceiver enable",
|
|
"debug transceiver disable",
|
|
"debug drivers",
|
|
"debug loopback-a",
|
|
"debug loopback-b",
|
|
"debug valid-test",
|
|
"debug uart-loopback",
|
|
"debug uart-suite",
|
|
"debug cts-flow-test",
|
|
"debug rts-flow-test",
|
|
"debug display",
|
|
"debug display status",
|
|
"debug display probe",
|
|
"debug display scan",
|
|
"debug display scan --force",
|
|
"debug display init",
|
|
"debug display init 0x3c",
|
|
"debug display init 0x78",
|
|
"debug display init 0x79",
|
|
"debug display init 0x3d",
|
|
"debug display init 0x7a",
|
|
"debug display init 0x7b",
|
|
"debug display off",
|
|
"debug display pattern",
|
|
"debug display pattern clear",
|
|
"debug display pattern fill",
|
|
"debug display pattern checker",
|
|
"debug display pattern grid",
|
|
"debug display pattern corners",
|
|
"debug display pattern layout",
|
|
"debug display row",
|
|
"debug display contrast",
|
|
"debug display invert",
|
|
"debug display invert on",
|
|
"debug display invert off",
|
|
"debug buttons",
|
|
"debug buttons status",
|
|
"debug buttons test",
|
|
|
|
/* Persistent local OLED aging settings. */
|
|
"display status",
|
|
"display set",
|
|
"display set dim-seconds",
|
|
"display set off-seconds",
|
|
"display save",
|
|
"display load",
|
|
"display defaults",
|
|
"display reset",
|
|
|
|
/* Serial service lifecycle, persistence, counters, and settings. */
|
|
"serial status",
|
|
"serial start",
|
|
"serial stop",
|
|
"serial set",
|
|
"serial set baud",
|
|
"serial set data-bits",
|
|
"serial set data-bits 7",
|
|
"serial set data-bits 8",
|
|
"serial set parity",
|
|
"serial set parity none",
|
|
"serial set parity even",
|
|
"serial set parity odd",
|
|
"serial set stop-bits",
|
|
"serial set stop-bits 1",
|
|
"serial set stop-bits 2",
|
|
"serial set flow",
|
|
"serial set flow none",
|
|
"serial set flow rts-cts",
|
|
"serial set dtr",
|
|
"serial set dtr inactive",
|
|
"serial set dtr active",
|
|
"serial set dtr on-connect",
|
|
"serial set rts-threshold",
|
|
"serial save",
|
|
"serial load",
|
|
"serial defaults",
|
|
"serial reset",
|
|
"serial counters",
|
|
"serial clear-counters",
|
|
|
|
/* Session broker inspection, ownership, and data operations. */
|
|
"broker status",
|
|
"broker clients",
|
|
"broker counters",
|
|
"broker clear-counters",
|
|
"broker connect",
|
|
"broker disconnect",
|
|
"broker request-writer",
|
|
"broker release-writer",
|
|
"broker force-writer",
|
|
"broker send-hex",
|
|
"broker read",
|
|
"broker events",
|
|
|
|
/* Native USB CDC status and writer ownership. */
|
|
"usb help",
|
|
"usb status",
|
|
"usb counters",
|
|
"usb clear-counters",
|
|
"usb request-writer",
|
|
"usb release-writer",
|
|
|
|
/* Physical role-based user, password, and SSH-key administration. */
|
|
"user status",
|
|
"user list",
|
|
"user show",
|
|
"user bootstrap",
|
|
"user bootstrap --generate",
|
|
"user recover --force",
|
|
"user add",
|
|
"user delete",
|
|
"user role",
|
|
"user password",
|
|
"user key add",
|
|
"user key delete",
|
|
"user key clear",
|
|
|
|
/* Wi-Fi lifecycle, persistence, profiles, AP policy, and diagnostics. */
|
|
"wifi status",
|
|
"wifi profiles",
|
|
"wifi counters",
|
|
"wifi clear-counters",
|
|
"wifi start",
|
|
"wifi stop",
|
|
"wifi reconnect",
|
|
"wifi save",
|
|
"wifi load",
|
|
"wifi defaults",
|
|
"wifi reset",
|
|
"wifi profile",
|
|
"wifi profile set",
|
|
"wifi profile secret",
|
|
"wifi profile enable",
|
|
"wifi profile disable",
|
|
"wifi profile delete",
|
|
"wifi ap",
|
|
"wifi ap policy",
|
|
"wifi ap policy off",
|
|
"wifi ap policy fallback",
|
|
"wifi ap policy always",
|
|
"wifi ap ssid",
|
|
"wifi ap channel",
|
|
"wifi ap secret",
|
|
"wifi ap show-secret",
|
|
"wifi ping",
|
|
"wifi nslookup",
|
|
"wifi traceroute",
|
|
|
|
/* Authenticated HTTPS lifecycle and physical-admin recovery operations. */
|
|
"web help",
|
|
"web status",
|
|
"web start",
|
|
"web stop",
|
|
"web counters",
|
|
"web clear-counters",
|
|
"web credentials",
|
|
"web credentials show",
|
|
"web credentials rotate",
|
|
"web credentials rotate --force",
|
|
"web certificate",
|
|
"web certificate info",
|
|
"web certificate rotate",
|
|
"web certificate rotate --force",
|
|
"web reset",
|
|
"web reset --force",
|
|
|
|
/* Authenticated SSH serial transport and independent host identity. */
|
|
"ssh help",
|
|
"ssh status",
|
|
"ssh start",
|
|
"ssh stop",
|
|
"ssh sessions",
|
|
"ssh disconnect",
|
|
"ssh counters",
|
|
"ssh clear-counters",
|
|
"ssh host-key",
|
|
"ssh host-key info",
|
|
"ssh host-key rotate",
|
|
"ssh host-key rotate --force",
|
|
"ssh reset",
|
|
"ssh reset --force",
|
|
};
|
|
|
|
static ssize_t console_read_with_late_terminal_upgrade(int file_descriptor,
|
|
void *buffer,
|
|
size_t size)
|
|
{
|
|
ssize_t received = read(file_descriptor, buffer, size);
|
|
if (received > 0 && linenoiseIsDumbMode()) {
|
|
/*
|
|
* The current line remains in the safe dumb reader. The next call to
|
|
* linenoise() starts enhanced mode only after a terminal has proven it
|
|
* can send data, so its cursor-position query cannot block unattended.
|
|
*/
|
|
linenoiseSetDumbMode(0);
|
|
}
|
|
return received;
|
|
}
|
|
|
|
static void console_completion_callback(const char *buffer, linenoiseCompletions *completions)
|
|
{
|
|
/* Preserve ESP-IDF completion for registered root command names. */
|
|
if (strchr(buffer, ' ') == NULL) {
|
|
esp_console_get_completion(buffer, completions);
|
|
return;
|
|
}
|
|
|
|
const size_t buffer_length = strlen(buffer);
|
|
for (size_t index = 0;
|
|
index < sizeof(s_completion_candidates) / sizeof(s_completion_candidates[0]);
|
|
++index) {
|
|
const char *const candidate = s_completion_candidates[index];
|
|
const size_t candidate_length = strlen(candidate);
|
|
|
|
/* linenoise expects the complete replacement line, not only its suffix. */
|
|
if (candidate_length > buffer_length &&
|
|
strncmp(candidate, buffer, buffer_length) == 0) {
|
|
linenoiseAddCompletion(completions, candidate);
|
|
}
|
|
}
|
|
}
|
|
|
|
void console_completion_install(void)
|
|
{
|
|
/* Preserve ESP-IDF's safe boot-time mode until actual UART input arrives. */
|
|
linenoiseSetReadFunction(&console_read_with_late_terminal_upgrade);
|
|
linenoiseSetCompletionCallback(&console_completion_callback);
|
|
}
|